I'm trying to use the new UISearchController
from iOS 8, and embed its UISearchBar
in my UINavigationBar
. That's easily done as follows:
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.titleView = searchController.searchBar
But when I add the scope buttons:
searchController.searchBar.showsScopeBar = true
searchController.searchBar.scopeButtonTitles = ["Posts, Users, Subreddits"]
It adds the buttons behind the UISearchBar
and obviously looks very odd.
How should I be doing this?
You're bumping into a "design issue" where the scopeBar
is expected to be hidden when the searchController
is not active.
The scope bar buttons appear behind (underneath) the search bar since that's their location when the search bar becomes active and animates itself up into the navigation bar.
When the search is not active, a visible scope bar would take up space on the screen, distract from the content, and confuse the user (since the scope buttons have no results to filter).
Since your searchBar
is already located in the titleView, the (navigation and search) bar animation that reveals the scope bar doesn't occur.
- The easiest option is to locate the search bar below the
navigation bar, and let the
searchBar
animate up into the title
area when activated. The navigation bar will animate its height,
making room to include the scope bar that was hidden. This will all
be handled by the search controller.
The second option, almost as easy, is to use a Search bar button
icon, which will animate the searchBar
and scopeBar
down into
view over the navigation bar.
- (IBAction)searchButtonClicked:(UIBarButtonItem *)__unused sender {
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.definesPresentationContext = YES;
self.searchController.searchBar.scopeButtonTitles = @[@"Posts", @"Users", @"Subreddits"];
[self presentViewController:self.searchController animated:YES completion:nil];
}
If you want the searchBar
to remain in the titleView, an animation
to do what you want is not built in. You'll have to roll your own
code to handle the navigationBar height change and display your own
scope bar (or hook into the internals, and animate the built-in
scopeBar
down and into view).
If you're fortunate, someone else has written willPresentSearchController:
code to handle the transition you want.
If you want to always see a searchBar
and scopeBar
, you'll probably have to ditch using the built-in scopeBar
, and replace it with a UISegmentedControl
which the user will always see, even when the search controller is not active.
Update:
This answer suggested subclassing UISearchController
to change its searchBar's height.