[英]iOS8 Cannot hide cancel button on search bar in UISearchController
My goal is to prevent the cancel button from appearing in a search bar in a UISearchController. 我的目标是阻止取消按钮出现在UISearchController的搜索栏中。 I started with Apple's Table Search with UISearchController sample code and hid the cancel button as seen in the code snip below.
我从Apple的Table Search开始, 使用UISearchController示例代码并隐藏了取消按钮,如下面的代码片段所示。 However, when the user taps in the text field, the cancel button still appears.
但是,当用户点击文本字段时,仍会显示取消按钮。 Any help?
有帮助吗?
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
...
I think there are three ways of achieving that: 我认为有三种方法可以实现这一目标:
searchController.searchBar.showsCancelButton = false
Subclass UISearchBar and override the layoutSubviews to change that var when the system attempts to draw it. 子类UISearchBar并覆盖layoutSubviews以在系统尝试绘制var时更改该var。
Register for keyboard notification UIKeyboardWillShowNotification and apply the code in point 1. 注册键盘通知UIKeyboardWillShowNotification并应用第1点中的代码。
Of course can always implement your search bar. 当然可以随时实现您的搜索栏。
For iOS 8, and UISearchController, use this delegate method from UISearchControllerDelegate
: 对于iOS 8,和UISearchController,使用该委托方法从
UISearchControllerDelegate
:
func didPresentSearchController(searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
Don't forget to set yourself as the delegate: searchController.delegate = self
不要忘记将自己设置为委托:
searchController.delegate = self
Simply subclass UISearchController
& UISearchBar
. 简单地
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 */ }
}
The following github project subclasses UISearchBar which is presented as solution 2: 以下github项目子类UISearchBar,它作为解决方案2呈现:
https://github.com/mechaman/CustomSearchControllerSwift https://github.com/mechaman/CustomSearchControllerSwift
On top of it, it also subclasses UISearchController to enable one to put the search bar in places other than the tableView header! 除此之外,它还是UISearchController的子类,使得人们可以将搜索栏放在tableView标题以外的位置!
Hope this helps. 希望这可以帮助。
This was the simplest solution I could come up with in Swift. 这是我在Swift中提出的最简单的解决方案。
Custom search controller: 定制搜索控制器:
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
}
}
Custom search bar: 自定义搜索栏:
class CustomSearchBar: UISearchBar {
override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
// do nothing
}
}
The most important piece of this was to only create the _searchBar
object once in init
vs. creating it inside of the stored property. 其中最重要的部分是只在
init
创建一次_searchBar
对象,而在存储的属性中创建它。
Just subclass your UISearchController and do the following: 只需子类化您的UISearchController并执行以下操作:
class CustomSearchController: UISearchController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
searchBar.showsCancelButton = false
}
}
This was the easiest solution I could came up with in order to solve the flashing cancel-button issue. 这是我能想出的最简单的解决方案,以解决闪烁的取消按钮问题。
TL;DR : Subclassing UISearchBar
and overriding setShowsCancelButton:
and setShowsCancelButton:animated:
hides the cancel button. TL; DR :子类化
UISearchBar
并覆盖setShowsCancelButton:
和setShowsCancelButton:animated:
隐藏取消按钮。
I set active
to NO
if the search bar is not the first responder (keyboard is not active and displayed), since that is effectively a cancel command. 如果搜索栏不是第一个响应者(键盘未激活并显示),我将
active
设置为NO
,因为这实际上是取消命令。
Marking searchController.searchBar.showsCancelButton = NO
doesn't seem to work in iOS 8 . 标记
searchController.searchBar.showsCancelButton = NO
似乎在iOS 8中不起作用。 I haven't tested iOS 9 . 我还没有测试iOS 9 。
Empty, but placed here for completeness. 空,但放在这里是为了完整。
@import UIKit;
@interface FJSearchBar : UISearchBar
@end
#import "FJSearchBar.h"
@implementation FJSearchBar
- (void)setShowsCancelButton:(BOOL)showsCancelButton {
// do nothing
}
- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated {
// do nothing
}
@end
Here's where you want to make the real changes. 这是你想要做出真正改变的地方。 I split the
UISearchBarDelegate
into its own category because, IMHO, the categories make the classes cleaner and easier to maintain. 我将
UISearchBarDelegate
拆分为自己的类别,因为恕我直言,这些类使类更清晰,更易于维护。 If you want to keep the delegate within the main class interface/implementation, you're more than welcome to do so. 如果您希望将委托保留在主类接口/实现中,那么非常欢迎您这样做。
@import UIKit;
@interface FJSearchController : UISearchController
@end
@interface FJSearchController (UISearchBarDelegate) <UISearchBarDelegate>
@end
#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
Some parts to note: 需要注意的部分内容:
BOOL
as private variables instead of properties because BOOL
作为私有变量而不是属性,因为
searchBar
is the first responder. searchBar
是否是第一个响应者。 If it's not, then we actually deactivate the search controller because the text is empty and we're no longer searching. searchText.length == 0
. searchText.length == 0
。 searchBar:textDidChange:
is invoked before searchBarShouldBeginEditing:
, which is why we handled it in this order. searchBar:textDidChange:
在searchBarShouldBeginEditing:
之前调用,这就是我们按此顺序处理它的原因。 [self.searchResultsUpdater updateSearchResultsForSearchController:self];
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
to searchBarSearchButtonClicked:
if you only want the search performed after the user presses the Search button. searchBarSearchButtonClicked:
如果您只想在用户按下“ 搜索”按钮后执行搜索 。 Swift: 迅速:
The following worked for me, added under viewDidLoad, because I never wanted that button: 以下为我工作,在viewDidLoad下添加,因为我从来不想要那个按钮:
let searchBarStyle = searchBar.value(forKey: "searchField") as? UITextField
searchBarStyle?.clearButtonMode = .never
Make sure to add the ID for the searchBar in the storyboard. 确保在故事板中添加searchBar的ID。
Use UISearchControllerDelegate. 使用UISearchControllerDelegate。
func willPresentSearchController(_ searchController: UISearchController) {
searchController.searchBar.setValue("", forKey:"_cancelButtonText")
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.