Prevent a UISearchDisplayController from hiding the navigation bar

IphoneIphone Sdk-3.0UinavigationcontrollerUisearchdisplaycontroller

Iphone Problem Overview


Whenever a user begins editing a UISearchDisplayController's search bar, the search controller becomes active and hides the view's navigation bar while presenting the search table view. Is it possible to prevent a UISearchDisplayController from hiding the navigation bar without reimplementing it?

Iphone Solutions


Solution 1 - Iphone

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.

Solution 2 - Iphone

The simplest solution and no hacks.

@interface MySearchDisplayController : UISearchDisplayController

@end

@implementation MySearchDisplayController

- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [super setActive: visible animated: animated];
    
    [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}

@end

Solution 3 - Iphone

The new UISearchController class introduced with iOS 8 has a property hidesNavigationBarDuringPresentation which you can set to false if you want to keep the navigation bar visible (by default it will still be hidden).

Solution 4 - Iphone

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].

Solution 5 - Iphone

Since iOS 8.0 the same behavior can be achieved by setting the UISearchController's self.searchController.hidesNavigationBarDuringPresentation property to false.

The code in Swift looks like this:

searchController.hidesNavigationBarDuringPresentation = false

Solution 6 - Iphone

Tried this a different way, without subclassing UISearchDisplayController. In your UIViewController class where you set the delegate for UISearchDisplayController, implement searchDisplayControllerDidBeginSearch: and add use

[self.navigationController setNavigationBarHidden:NO animated:YES];

Did the trick for me, hope that helps.

Solution 7 - Iphone

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 https://stackoverflow.com/q/1614687/594211). 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;
}

Solution 8 - Iphone

Really nice solution, but it was crashing my app under iOS6. I had to make the following modification to get it work.

@implementation ICSearchDisplayController
    
    - (void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        if (visible == YES) {
            [super setActive:visible animated:animated];
            [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        } else {
            [super setActive:NO animated:NO];
        }
    }

Solution 9 - Iphone

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];
}

Solution 10 - Iphone

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

Solution 11 - Iphone

I think the best solution is to implement the UISearchDisplayController yourself.

It's not that difficult. You only need to implement UISearchBarDelegate for your UIViewController and include a UITableView to display your search results.

Solution 12 - Iphone

@Pavel's works perfectly well. However, I was trying to get this into a UIPopoverController and the text in the field gets pushed slightly when the search bar's text field becomes the first responder, and that looks a bit ugly, so I fixed it by calling the super method with animated set to NO.

Solution 13 - Iphone

As jrc pointed out "unhook UISearchDisplayController from controlling any UISearchBar" seems to work for me. If I pass nil as a parameter when creating UISearchDisplayController the navigation bar stays visible at all times:

searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];

Solution 14 - Iphone

I was adding custom navigation bar on my ViewController which was getting hidden on search, a quick but not so good fix was

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    [self.view addSubview:_navBar];
}

_navBar is UINavigationBar added programmatically, doing this helped me navigation bar from hiding.

Solution 15 - Iphone

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];
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhadronzooView Question on Stackoverflow
Solution 1 - IphonestigiView Answer on Stackoverflow
Solution 2 - IphonePavel SharandaView Answer on Stackoverflow
Solution 3 - IphoneRenéView Answer on Stackoverflow
Solution 4 - IphonejoerickView Answer on Stackoverflow
Solution 5 - IphonePeter IvanicsView Answer on Stackoverflow
Solution 6 - Iphoneah335View Answer on Stackoverflow
Solution 7 - IphonejrcView Answer on Stackoverflow
Solution 8 - IphoneJohn SalernoView Answer on Stackoverflow
Solution 9 - IphoneDaniel RyanView Answer on Stackoverflow
Solution 10 - IphonePaul PeelenView Answer on Stackoverflow
Solution 11 - IphonefrankliView Answer on Stackoverflow
Solution 12 - IphoneXCoolView Answer on Stackoverflow
Solution 13 - IphoneDasha SaloView Answer on Stackoverflow
Solution 14 - IphonesahiljainView Answer on Stackoverflow
Solution 15 - Iphonealex1704View Answer on Stackoverflow