22

我的目标是防止取消按钮出现在 UISearchController 的搜索栏中。我从带有UISearchController 示例代码的 Apple 表格搜索开始,并隐藏了取消按钮,如下面的代码片段所示。但是,当用户在文本字段中点击时,仍会出现取消按钮。有什么帮助吗?

override func viewDidLoad() {
    super.viewDidLoad()

    resultsTableController = ResultsTableController()

    searchController = UISearchController(searchResultsController: resultsTableController)
    searchController.searchResultsUpdater = self
    searchController.searchBar.sizeToFit()
    tableView.tableHeaderView = searchController.searchBar

    searchController.searchBar.delegate = self

    //Hide cancel button - added by me
    searchController.searchBar.showsCancelButton = false

    ...
4

9 回答 9

21

我认为有以下三种方法可以实现:

  1. 覆盖searchDisplayControllerDidBeginSearch并使用以下代码:

searchController.searchBar.showsCancelButton = false

  1. 子类 UISearchBar 并覆盖 layoutSubviews 以在系统尝试绘制它时更改该 var。

  2. 注册键盘通知UIKeyboardWillShowNotification并应用第1 点中的代码。

当然可以随时实现你的搜索栏。

于 2014-11-05T23:46:51.637 回答
17

对于 iOS 8 和 UISearchController,请使用以下委托方法UISearchControllerDelegate

func didPresentSearchController(searchController: UISearchController) {
  searchController.searchBar.showsCancelButton = false
}

不要忘记将自己设置为代表:searchController.delegate = self

于 2015-07-09T16:27:01.197 回答
15

简单地继承UISearchController& UISearchBar

class NoCancelButtonSearchController: UISearchController {
    let noCancelButtonSearchBar = NoCancelButtonSearchBar()
    override var searchBar: UISearchBar { return noCancelButtonSearchBar }
}

class NoCancelButtonSearchBar: UISearchBar {
    override func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) { /* void */ }
}
于 2016-12-22T01:59:52.317 回答
3

以下 github 项目子类 UISearchBar 作为解决方案 2 呈现:

https://github.com/mechaman/CustomSearchControllerSwift

最重要的是,它还继承了 UISearchController 以允许将搜索栏放在 tableView 标题以外的位置!

希望这可以帮助。

于 2015-08-20T11:01:19.180 回答
2

只需子类化您的 UISearchController 并执行以下操作:

class CustomSearchController: UISearchController {

   override func viewDidLayoutSubviews() {
       super.viewDidLayoutSubviews()
       searchBar.showsCancelButton = false
   }
}

这是我能想到的最简单的解决方案,以解决闪烁的取消按钮问题。

于 2017-06-12T06:32:48.353 回答
2

这是我在 Swift 中能想到的最简单的解决方案。

自定义搜索控制器:

class CustomSearchController: UISearchController {

    var _searchBar: CustomSearchBar

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        self._searchBar = CustomSearchBar()
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    override init(searchResultsController: UIViewController?) {
        self._searchBar = CustomSearchBar()
        super.init(searchResultsController: searchResultsController)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var searchBar: UISearchBar {
        return self._searchBar
    }
}

自定义搜索栏:

class CustomSearchBar: UISearchBar {
    override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
        // do nothing
    }
}

其中最重要的部分是只创建_searchBar一次对象,init而不是在存储属性中创建它。

于 2016-03-07T02:13:12.970 回答
1

TL;DR:子类化UISearchBar和覆盖setShowsCancelButton:setShowsCancelButton:animated:隐藏取消按钮。

解决方案

如果搜索栏不是第一响应者(键盘未激活并显示),我设置active为,因为这实际上是一个取消命令。NO

FJ搜索栏

标记searchController.searchBar.showsCancelButton = NO似乎在iOS 8中不起作用。我还没有测试过iOS 9

FJSearchBar.h

空的,但为了完整起见放在这里。

@import UIKit;

@interface FJSearchBar : UISearchBar

@end

FJSearchBar.m

#import "FJSearchBar.h"

@implementation FJSearchBar

- (void)setShowsCancelButton:(BOOL)showsCancelButton {
    // do nothing
}

- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated {
    // do nothing
}

@end

FJSearchController

这是您要进行真正更改的地方。我将其拆分UISearchBarDelegate为自己的类别,因为恕我直言,这些类别使类更清洁且更易于维护。如果您想将委托保留在主类接口/实现中,我们非常欢迎您这样做。

FJSearchController.h

@import UIKit;

@interface FJSearchController : UISearchController

@end

@interface FJSearchController (UISearchBarDelegate) <UISearchBarDelegate>

@end

FJSearchController.m

#import "FJSearchController.h"
#import "FJSearchBar.h"

@implementation FJSearchController {
@private
    FJSearchBar *_searchBar;
    BOOL _clearedOutside;
}

- (UISearchBar *)searchBar {
    if (_searchBar == nil) {
        // if you're not hiding the cancel button, simply uncomment the line below and delete the FJSearchBar alloc/init
        // _searchBar = [[UISearchBar alloc] init];
        _searchBar = [[FJSearchBar alloc] init];
        _searchBar.delegate = self;
    }
    return _searchBar;
}

@end

@implementation FJSearchController (UISearchBarDelegate)

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    // if we cleared from outside then we should not allow any new editing
    BOOL shouldAllowEditing = !_clearedOutside;
    _clearedOutside = NO;
    return shouldAllowEditing;
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // hide the keyboard since the user will no longer add any more input
    [searchBar resignFirstResponder];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (![searchBar isFirstResponder]) {
        // the user cleared the search while not in typing mode, so we should deactivate searching
        self.active = NO;
        _clearedOutside = YES;
        return;
    }
    // update the search results
    [self.searchResultsUpdater updateSearchResultsForSearchController:self];
}

@end

一些需要注意的部分:

  1. 我把搜索栏和BOOL作为私有变量而不是属性,因为
    • 它们比私有属性更轻量级。
    • 它们不需要被外界看到或修改。
  2. 我们检查是否searchBar是第一响应者。如果不是,那么我们实际上停用了搜索控制器,因为文本为空并且我们不再搜索。如果你真的想确定,你也可以确保searchText.length == 0.
  3. searchBar:textDidChange:在之前调用searchBarShouldBeginEditing:,这就是我们按此顺序处理它的原因。
  4. 每次文本更改时,我都会更新搜索结果,但如果您只想在用户按下“搜索”按钮后执行搜索,则可能需要将其[self.searchResultsUpdater updateSearchResultsForSearchController:self];移至。searchBarSearchButtonClicked:
于 2016-03-06T06:07:58.377 回答
1

迅速:

以下对我有用,添加在 viewDidLoad 下,因为我从不想要那个按钮:

let searchBarStyle = searchBar.value(forKey: "searchField") as? UITextField
searchBarStyle?.clearButtonMode = .never

确保在情节提要中添加 searchBar 的 ID。 在此处输入图像描述

于 2018-06-09T17:45:22.470 回答
0

使用 UISearchControllerDelegate。

func willPresentSearchController(_ searchController: UISearchController) {

        searchController.searchBar.setValue("", forKey:"_cancelButtonText")
    }
于 2017-04-10T04:57:58.220 回答