防止UISearchDisplayController隐藏导航栏

每当用户开始编辑UISearchDisplayController的search栏时,search控制器将变为活动状态,并在呈现search表视图时隐藏视图的导航栏。 是否有可能阻止UISearchDisplayController隐藏导航栏而不重新实现?

iOS 8引入的新的UISearchController类有一个属性hidesNavigationBarDuringPresentation ,如果你想让导航栏保持可见状态(默认情况下它仍然是隐藏的),你可以设置为false。

我只是debugging了一下到UISearchDisplayController,发现它调用UINavigationController上的私有方法来隐藏导航栏。 这发生在-setActive:animated :. 如果您inheritanceUISearchDisplayController并使用以下代码覆盖此方法,则可以通过将导航条伪装为已隐藏来防止导航条被隐藏。

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

让我知道这是否适合你。 我也希望这将不会在未来的iOS版本中打破…只在iOS 4.0上testing。

最简单的解决scheme,没有黑客。

 @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 

以上的答案对我来说并不适合。 我的解决scheme是愚弄UISearchDisplayController认为没有UINavigationController。

在你的视图控制器中,添加这个方法

 - (UINavigationController *)navigationController { return nil; } 

这对我来说没有任何不良的副作用,尽pipe看起来像一个非常糟糕的主意…如果你需要在导航控制器,使用[super navigationController]控制器[super navigationController]

尝试了这种不同的方式,没有UISearchDisplayController的inheritance。 在您设置UISearchDisplayController的委托的UIViewController类中,实现searchDisplayControllerDidBeginSearch:并添加使用

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

对我来说有窍门,希望有所帮助。

从iOS 8.0开始,通过将UISearchControllerself.searchController.hidesNavigationBarDuringPresentation属性设置为false,可以实现相同的行为。

Swift中的代码如下所示:

 searchController.hidesNavigationBarDuringPresentation = false 

我遇到了一个稍微不同的问题。 在使用UISearchDisplayController时,我希望search栏位于导航栏中(而不是)。

将search栏放在导航栏中并不困难(请参阅UISearchBar和UINavigationItem )。 但是,UISearchDisplayController假定search栏始终位于导航栏的下方,并且(如此处所述)坚持在进入search时隐藏导航栏,所以看起来很糟糕。 此外,UISearchDisplayController给search栏打上淡淡的色彩。

我find了解决scheme。 诀窍是(反直觉地)解除UISearchDisplayController从任何UISearchBar的控制。 如果使用xib,这意味着删除search栏实例,或者至less解开插口。 然后创build你自己的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; } 

当用户点击search栏(在-searchBarShouldBeginEditing:时,您将需要手动激活search显示控制器,并在用户结束search时(在-searchDisplayControllerWillEndSearch:手动closuressearch栏。

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

真的很好的解决scheme,但它是在iOS6下崩溃我的应用程序。 我不得不作出以下修改,以使其工作。

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

这似乎为我解决了这个问题。 在iOS5 / 6.1中testing。 没有视觉问题,我可以看到。

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

iOS 7把事情搞砸了一点,对我来说这个工作很完美:

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

显示/隐藏状态栏的原因

我认为最好的解决scheme是自己实现UISearchDisplayController。

这并不困难。 你只需要为你的UIViewController实现UISearchBarDelegate,并包含一个UITableView来显示你的search结果。

@帕维尔的作品非常好。 不过,我试图把它放到一个UIPopoverController中,当search栏的文本字段成为第一个响应者时,字段中的文本被轻微地推动,而且看起来有点难看,所以我通过调用animated集的super方法来修复它到NO

正如jrc指出“解除UISearchDisplayController从控制任何UISearchBar”似乎为我工作。 如果我在创buildUISearchDisplayController时将nil作为parameter passing,导航栏始终保持可见:

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

我在我的ViewController上添加了自定义的导航栏,这个导航栏在search时隐藏起来了,但是并不是很好

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

_navBar是UINavigationBar以编程方式添加,这样做帮助我隐藏导航栏。

只是想添加stigi答案。 当您取消search并再次开始search时,search结果表格将不会对触摸做出反应,因此您需要添加下一行

 self.searchResultsTableView.alpha = 1; 

所以更新的代码看起来下一个方法

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