隐藏UISearchBar的取消按钮

28

我有一个UISearchDisplayController和UISearchBar通过我的Nib文件与ViewController关联起来。

我想隐藏取消按钮,以便用户永远看不到它。问题在于,以下代码隐藏了该按钮,但是仅在将其显示给用户一毫秒后才隐藏(例如,在模拟器和设备上闪现然后消失)。

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{
    controller.searchBar.showsCancelButton = NO;
}

有没有更好的方式来隐藏它?

11个回答

39

我成功地隐藏了“取消”按钮,方法是通过子类化 UISearchBar 并重写以下方法:

-(void)layoutSubviews{
    [super layoutSubviews];
    [self setShowsCancelButton:NO animated:NO];
}

1
这个方法可行!我创建了一个带有搜索功能的视图控制器,然后将整个视图控制器放在 iPad 弹出窗口中。显然,在 iPad 弹出窗口中不需要“取消”按钮,因此我正在寻找一种不需要取消按钮的解决方案,而这个方法就可以实现! - Wayne Liu
2
这个非常好用!我想我尝试了所有其他描述的方法来修复它,以避免子类化,但是无法完成!但是这个完美地解决了它!谢谢! - Kent Robin
这对我不起作用,我采用了BFeher的通知方式。 - paulvs
5
你可以使用视图控制器的 -viewWillLayoutSubviews 方法,而不是子类化 UISearchBar。这对我很有效! - maxkonovalov
3
虽然这个方法起作用了,但是在搜索控制器变为非活动状态再次变为活动状态后,导致光标停止出现。 我的解决方案是在我的UISearchBar子类中覆盖setShowsCancelButton:animated:方法,并调用[super setShowsCancelButton:NO animated:animated];。这将使取消按钮保持隐藏并解决我缺失光标的问题。 - beebcon
显示剩余2条评论

15

我也遇到了同样的问题,但是用了不同的方法解决了它。

对于那些无法或不想子类化UISearchDisplayController的人,我通过在UIKeyboardWillShowNotification上添加监听器并在那里设置[self setShowsCancelButton:NO animated:NO]来解决了这个问题。

viewWillAppear:中:

// Add keyboard observer:
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillAppear:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

然后你创建:

- (void)keyboardWillAppear:(NSNotification *)notification
{
    [YOUR-SEARCHBAR-HERE setShowsCancelButton:NO animated:NO];
}

别忘了添加,

[[NSNotificationCenter defaultCenter] removeObserver:self];

viewWillDisappear:方法中!

希望这可以帮助您!


如果在点击之前键盘已经打开,那么它将无法完美工作。 - Cœur

7

类似Nimrod的答案,您也可以子类化UISearchDisplayController并实现setActive:animated:方法:

- (void)setActive:(BOOL)visible animated:(BOOL)animated {
    [super setActive:visible animated:animated];
    self.searchBar.showsCancelButton = NO;
}

6
这似乎是Xcode中的一个错误。我已经将此错误提交到苹果的错误报告网站,并且他们跟进询问更多的示例代码和用例。
感谢各位尝试解决这个问题。

2
我遇到了相反的问题。我已经尝试使用nib文件和编程方式创建UISearchDisplayController和UISearchBar,但是我需要一直显示取消按钮而不是隐藏它。在控制器中,我将按钮设置为可见状态,在几个代理方法中也是如此,但是当我取消搜索时,按钮会消失然后重新出现。希望很快能解决这个问题。 - Byron Rode
2
他们回复说这是一个已知问题,他们正在努力修复。 - ArtSabintsev
很高兴他们意识到了这一点,这让我的搜索栏看起来有点糟糕。在此期间需要使用自定义按钮。 - Byron Rode

3
class CustomSearchBar: UISearchBar {

    override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
        super.setShowsCancelButton(false, animated: false)
    }

}

class CustomSearchController: UISearchController, UISearchBarDelegate {

    lazy var _searchBar: CustomSearchBar = {
        [unowned self] in
        let customSearchBar = CustomSearchBar(frame: CGRectZero)
        customSearchBar.delegate = self
        return customSearchBar
    }()

    override var searchBar: UISearchBar {
        get {
            return _searchBar
        }
    }

}

这很好用。但我不明白设置搜索栏代理的必要性。 - Mark Krenek
对我有用。同意@MarkKrenek的观点,设置委托不应该是必要的。我将其删除后仍然可以正常工作。 - John Scalo

3
在使用UISearchBarUISearchController时出现了问题。由于在iPad上showsCancelButton = YES时取消按钮未显示,我在使用自己的取消按钮,在iPhone上设置showsCancelButton = NO后,它现在不会消失!

以下是解决方法。

设置委托和初始值:

- (void)viewDidLoad
{
    // ... 
    self.searchController.searchBar.showsCancelButton = NO;
    self.searchController.searchBar.delegate = self;
}

当文本框开始编辑后的0.1秒,将showsCancelButton重置为NO

#pragma mark - UISearchBarDelegate
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        self.searchController.searchBar.showsCancelButton = NO;
    });
}

谢谢你的回答。它对我隐藏取消按钮很有用。 - Ramakrishna
这个可以工作,但是在展示时会有一些奇怪的动画,显示/隐藏按钮。 - Nemanja

2

如果你想避免子类化,实现

searchController.searchBar.showsCancelButton = false;

在这两个代理方法中(不要忘记分配代理):
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController

- (void)didPresentSearchController:(UISearchController *)searchController
第一个函数在每次更新搜索栏时调用(取消按钮默认可见),第二个函数用于第一次激活搜索栏。

完美!不想派生子类! - SergioM
听起来很有前途,但在我的iOS 12.1上没有起作用。取消按钮会短暂地显示,然后消失。 - John Scalo

0

根据我以前遇到的问题,你尝试过将其设置为:

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller

我不知道如何在你的问题中提出这个问题,如果这不合适,请原谅。


所以在创建UISearchDisplayController时,您需要配置取消按钮,而不是等待它开始搜索。 - jamesC

0
如果在搜索栏的搜索字段编辑时出现取消按钮,您可以执行以下操作:子类化搜索栏并使其实现UITextFieldDelegate协议:
@interface CustomAlignedSearchBar : UISearchBar<UITextFieldDelegate>

然后实现textFieldDidBeginEditing:并执行以下操作:

- (void)textFieldDidBeginEditing:(UITextField *)textField{
    [self setShowsCancelButton:self.cancelButtonShown animated:NO];
}

这将确保取消按钮不会显示出来。


MLUISearchBar.m:25:37: 在类型为 'MLUISearchBar *' 的对象上未找到属性 'cancelButtonShown'。构建错误。 - Gank

0

iOS8之后,UISearchDisplayController被弃用,苹果将搜索展示的处理交给了UISearchControllerDelegate。

因此,您可以重写searchBar来隐藏取消按钮,如下所示:

- (void)didPresentSearchController:(UISearchController *)searchController {
    [searchController.searchBar setShowsCancelButton:NO];
}

如果您需要在非活动状态下隐藏取消按钮,则需要在初始化时设置searchBar:
search = [[UISearchController alloc] initWithSearchResultsController:nil];
[search.searchBar setShowsCancelButton:NO];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接