Search code examples
iosuitableviewuisearchbaruisearchcontroller

UISearchController: Section Index of UITableView overlaps searchBar


I'm building an iOS 8 app that uses the new UISearchController. In the table view related to the search controller, I'm using a section index to let users jump quickly from one section of the table to the next. It's working just fine, but the section index overlaps the search bar on the table / search controller. Has anyone run into this issue before and, if so, how did you solve it? Below is how I'm initializing my search controller:

self.resultsTableController = [self.storyboard instantiateViewControllerWithIdentifier:[SelectSpecialtySearchResultsTVC storyboardId]];
UINavigationController *searchResultsNavController = [[UINavigationController alloc]initWithRootViewController:self.resultsTableController];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsNavController];

self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.searchBar.barTintColor = [UIColor colorWithHexString:kColorGrayLight];
self.searchController.searchBar.translucent = NO;
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, [self.view bounds].size.width, 44.0);
self.searchController.searchBar.delegate = self;

self.tableView.tableHeaderView = self.searchController.searchBar;

//present the search display controller within the confines of this class's table view
self.definesPresentationContext = YES;

// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.resultsTableController.tableView.delegate = self;
self.searchController.delegate = self;

enter image description here


Solution

  • Finally came up with an acceptable solution to this question. This answer builds off of my question above (I'm using all the same code minus what is changed here). The main thing to note here is that @andrewbuilder was right - adding the search bar as a table header view will guarantee that the search bar will move on scroll; it's just acting like any other table header view.

    What I ended up doing was a combination of things. The main change I made in my approach was changing the way my main controller presents my search controller. Specifically, I went from self.definesPresentationContext = YES; to self.definesPresentationContext = NO;

    What this does is essentially presents your search controller on top of your main screen rather than within it. This creates a design trade-off in the fact that you now have to deal with the layout of 2 view controllers rather than just one. But that was something I was ok with.

    The next thing I did was create a strong pointer to a UISearchBar in my main view controller, which I called searchBar. Then, I set that property to be equal to my search controller's searchBar and added it to my subview like so:

    self.searchBar = self.searchController.searchBar;
    [self.view addSubview:self.searchBar];
    

    In order to get this to look right, I had to make sure my table's x position was equal to the bottom of the search bar's frame. You can do that in many ways: either in code, in Interface Builder, or with a combination of both. I'll leave you to figure out the right choice for yourself.

    Again, the tradeoff here is that you have to set up two view controllers and make it look like it's the same screen even though it's not (customizing the nav bar, handling segues, etc). This seems to be a necessary evil that me and my team were willing to accept. From here, the next steps in getting this all working was messing with the edgesForExtendedLayout property on both view controllers (as well as the contentInset of the table views). I'm not going to write that code here since it will probably be different for everyone depending on their design. However, that's the gist of it.

    Please feel free to add to this thread if you find a simpler solution. I searched far and wide, but with UISearchController being a very new control, there's not a lot of documentation / info on it (and its quirks).