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