66

每当用户开始编辑UISearchDisplayController的搜索栏时,搜索控制器就会激活并隐藏视图的导航栏,同时呈现搜索表视图。是否可以防止UISearchDisplayController隐藏导航栏而不重新实现它?

4

15 回答 15

60

我只是对 UISearchDisplayController 进行了一些调试,发现它正在调用 UINavigationController 上的私有方法来隐藏导航栏。这发生在 -setActive:animated: 中。如果你继承 UISearchDisplayController 并用下面的代码覆盖这个方法,你可以通过假装它已经隐藏来防止导航栏被隐藏。

- (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 上测试。

于 2010-07-15T16:00:50.183 回答
52

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

@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
于 2012-09-21T11:47:02.530 回答
51

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

于 2014-10-21T09:49:04.517 回答
28

上面的答案对我来说不太合适。我的解决方案是欺骗 UISearchDisplayController 认为没有 UINavigationController。

在您的视图控制器中,添加此方法

- (UINavigationController *)navigationController {
    return nil;
}

尽管这似乎是一个非常糟糕的主意,但这对我来说没有任何不良副作用……如果您需要使用导航控制器,请使用[super navigationController].

于 2011-05-02T17:37:26.123 回答
10

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

Swift 中的代码如下所示:

searchController.hidesNavigationBarDuringPresentation = false
于 2016-02-04T08:18:19.000 回答
9

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

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

为我做了诀窍,希望有帮助。

于 2010-10-23T17:26:50.500 回答
4

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

将搜索栏放在导航栏中并不难(参见UISearchBar 和 UINavigationItem)。但是,UISearchDisplayController 假定搜索栏始终位于导航栏下方,并且(如这里所讨论的)坚持在输入搜索时隐藏导航栏,因此看起来很糟糕。此外,UISearchDisplayController 使搜索栏的颜色比正常颜色浅。

我找到了解决方案。诀窍是(反直觉地)将 UISearchDisplayController 完全从控制任何 UISearchBar 中解脱出来。如果使用 xibs,这意味着删除搜索栏实例,或者至少解开插座。然后创建自己的 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;
}

您需要在用户点击搜索栏时手动激活搜索显示控制器(在 中-searchBarShouldBeginEditing:),并在用户结束搜索时手动关闭搜索栏(在 中-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;
}
于 2011-12-21T23:13:12.347 回答
3

非常好的解决方案,但它在 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];
        }
    }
于 2012-12-08T17:52:28.533 回答
3

这似乎为我解决了这个问题。在 iOS5/6.1 中测试。没有我能看到的视觉问题。

- (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];
}
于 2013-03-12T01:32:32.860 回答
3

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

显示/隐藏状态栏的原因

于 2014-03-27T10:09:49.473 回答
1

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

这并不难。您只需要为您的 UIViewController 实现 UISearchBarDelegate 并包含一个 UITableView 来显示您的搜索结果。

于 2011-08-23T02:08:49.750 回答
0

我在我的 ViewController 上添加了自定义导航栏,该导航栏在搜索时被隐藏了,一个快速但不太好的修复是

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

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

于 2015-02-10T06:08:53.937 回答
0

正如 jrc 指出的那样,“从控制任何 UISearchBar 中解开 UISearchDisplayController”似乎对我有用。如果我在创建 UISearchDisplayController 时将 nil 作为参数传递,则导航栏始终保持可见:

searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];
于 2013-04-15T08:34:46.300 回答
0

@Pavel 的作品非常好。但是,我试图将其放入 UIPopoverController 中,当搜索栏的文本字段成为第一响应者时,字段中的文本会被轻微推送,这看起来有点难看,所以我通过调用set to的super方法 来修复它。animatedNO

于 2012-12-08T09:54:08.990 回答
0

只是想添加到 stigi 答案。当您取消搜索并重新开始搜索时 - 搜索结果表不会对触摸做出反应,因此您需要添加下一行

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];
    }
}
于 2015-07-29T10:53:43.893 回答