Whenever a user begins editing a UISearchDisplayController
\'s search bar, the search controller becomes active and hides the view\'s navigation bar while presen
Just wanted to add to stigi answer. When you cancel search and start search again - search results table won't be react to touches so you need to add next line
self.searchResultsTableView.alpha = 1;
So updated code looks next way
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
if(self.active == visible) return;
if (visible) {
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
self.searchResultsTableView.alpha = 1;
[self.searchBar becomeFirstResponder];
} else {
[super setActive:visible animated:animated];
[self.searchBar resignFirstResponder];
}
}
I just debugged a bit into UISearchDisplayController and found that it's calling a private method on UINavigationController to hide the navigation bar. This happens in -setActive:animated:. If you subclass UISearchDisplayController and overwrite this method with the following code you can prevent the navigationBar from being hidden by faking it to be already hidden.
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
if(self.active == visible) return;
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
if (visible) {
[self.searchBar becomeFirstResponder];
} else {
[self.searchBar resignFirstResponder];
}
}
Let me know if this works for you. I also hope this won't break in future iOS versions... Tested on iOS 4.0 only.
This seem to solve it for me. Tested in both iOS5/6.1. No visual issues that I could see.
- (void)viewDidAppear
{
[super viewDidAppear];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillAppear:(NSNotification *)notification
{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
-(void)viewDidLayoutSubviews{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
I ran into this while tackling a slightly different problem. While using UISearchDisplayController, I want the search bar to be in the navigation bar (not under).
It's not hard to put the search bar in the navigation bar (see UISearchBar and UINavigationItem). However, UISearchDisplayController assumes the search bar is always underneath the navigation bar and (as discussed here) insists on hiding the navigation bar when entering search, so things look awful. Additionally, UISearchDisplayController tints the search bar lighter than normal.
I found a solution. The trick is to (counter-intuitively) unhook UISearchDisplayController from controlling any UISearchBar at all. If using xibs, this means deleting the search bar instance, or at least unhooking the outlet. Then create your own UISearchBar:
- (void)viewDidLoad
{
[super viewDidLoad];
UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
[searchBar sizeToFit]; // standard size
searchBar.delegate = self;
// Add search bar to navigation bar
self.navigationItem.titleView = searchBar;
}
You will need to manually activate the search display controller when the user taps the search bar (in -searchBarShouldBeginEditing:
) and manually dismiss the search bar when the user ends searching (in -searchDisplayControllerWillEndSearch:
).
#pragma mark <UISearchBarDelegate>
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
// Manually activate search mode
// Use animated=NO so we'll be able to immediately un-hide it again
[self.searchDisplayController setActive:YES animated:NO];
// Hand over control to UISearchDisplayController during the search
searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;
return YES;
}
#pragma mark <UISearchDisplayDelegate>
- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {
// Un-hide the navigation bar that UISearchDisplayController hid
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {
UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;
// Manually resign search mode
[searchBar resignFirstResponder];
// Take back control of the search bar
searchBar.delegate = self;
}
iOS 7 screws things up a bit... for me this worked perfectly:
/**
* Overwrite the `setActive:animated:` method to make sure the UINavigationBar
* does not get hidden and the SearchBar does not add space for the statusbar height.
*
* @param visible `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
* @param animated `YES` to use animation for a change in visible state, otherwise NO.
*/
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}
The reason for show/hide the statusbar
The above answers didn't work quite right for me. My solution is to fool the UISearchDisplayController into thinking there wasn't a UINavigationController.
In your view controller, add this method
- (UINavigationController *)navigationController {
return nil;
}
This had no untoward side effects for me, despite seeming like a really bad idea... If you need to get at the navigation controller, use [super navigationController]
.