更新搜索的内容
在UISearchControllerDelegate代理方法updateSearchResultsForSearchController中通过以下的代码来实现搜索的数据更新:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchText = searchController.searchBar.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SELF CONTAINS %@)", searchText];
filterArr = searchText.length>0?[dataArr filteredArrayUsingPredicate:predicate]:dataArr; //当搜索内容清空后也有内容
[self.tableView reloadData];
}
结果展示控制器问题
EOCSearchResultViewCtrl *resultSearchCtrl = [[EOCSearchResultViewCtrl alloc] init];
_searchCtrl = [[UISearchController alloc] initWithSearchResultsController:resultSearchCtrl];
在初始化UISearchController的时候initWithSearchResultsController如果设置为自己的话,设置成nil就好,不要设置成self,当设置为nil的时候也就是说搜索的结果,会在self中进行展示,当然一般是在self中用tableview进行展示。如果设置为别的控制器,就会展示在别的控制器中,其实也就只是相当于拆分开来罢了。
searchBar的问题
[self.view addSubview:self.tableView];
[self.tableView setTableHeaderView:self.searchCtrl.searchBar];
我们将searchBar设置为tableView的头视图,并且当点击搜索框的时候,在UISearchControllerDelegate代理的willPresentSearchController方法和didPresentSearchController方法分别打断点可得以下结果:

以上是打断点过后的图

以上是点击搜索框之前的图

以上是点击搜索框之后的图
从上可以知道当点击了searchBar过后,系统将searchBar取出来移到了导航栏上面,而不再是tableView的头视图,而且点击之前和之后的searchBar是同一个,查看他们的内存地址可以知道。
另外需要注意的点
- 当使用搜索框的时候最好不要将self.automaticallyAdjustsScrollViewInsets设置为NO,因为会很难调坐标,会出现64px的问题。
- 搜索框也能添加在scrollView上面
- searchController必须设置成成员变量,否则只会是添加了一个view上去,而其代理方法那些都不会响应,因为你不设置成成员变量,出了那个方法,你就不释放掉了
-
definesPresentationContext 当SearchResultsController不为nil,即搜索结果在别的控制器展示的时候,需要将definesPresentationContext设置为YES,即表示当UISearchController控制器present到需要展示的目标控制器的时候,可以覆盖当前的控制器,否则当跳到目标控制器时,上面会有一段空白
修改搜索框的一些设置
//修改背景色
self.searchCtrl.searchBar.barTintColor = [UIColor yellowColor];
//修改光标和取消文字颜色
self.searchCtrl.searchBar.tintColor = [UIColor orangeColor];
//修改图标
[self.searchCtrl.searchBar setImage:[UIImage imageNamed:@"voice_gray"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
[self.searchCtrl.searchBar setImage:[UIImage imageNamed:@"message_gray"] forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
[self.searchCtrl.searchBar setImage:[UIImage imageNamed:@"message_gray"] forSearchBarIcon:UISearchBarIconClear state:UIControlStateHighlighted];
// KVC 修改textfield的文字
UITextField *textField = [self.searchCtrl.searchBar valueForKey:@"_searchField"];
textField.textColor = [UIColor orangeColor];
textField.font = [UIFont systemFontOfSize:12.f];
// KVC 修改textfield的默认提示文字 两级就用keyPath
[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
// KVC 修改searchBar的取消按钮文字 两级就用keyPath
[self.searchCtrl.searchBar setValue:@"取消" forKey:@"_cancelButtonText"];
上面是使用KVC来进行修改,也可以通过遍历的方法来进行修改,但是进行搜索过后,进入SearchResultsController后就回到了原状。
半定制搜索框
没有实现当点击搜索框的时候,会跳到导航条,但是可以改变textfield的大小,用系统的改变不了。自定义搜索框需要自定义UISearchController和UISearchBar。代码如下:
EOCClassSearchCtl:
#import <UIKit/UIKit.h>
#import "EOCClassSearchBar.h"
@protocol EOCClassSearchCtrlDelegate <NSObject>
- (void)didStartSearching;
- (void)didTapSearchBtn;
- (void)didTapCancelBtn;
- (void)didChangeSearchText:(NSString *)text;
@end
@interface EOCClassSearchCtl : UISearchController
@property(nonatomic, strong)EOCClassSearchBar *classSearchBar;
@property(nonatomic, weak)id <EOCClassSearchCtrlDelegate> classSearchCtrlDelegate;
@end
#import "EOCClassSearchCtl.h"
@interface EOCClassSearchCtl ()<UISearchBarDelegate>
@end
@implementation EOCClassSearchCtl
- (instancetype)initWithSearchResultsController:(UIViewController *)searchResultsController {
if (self = [super initWithSearchResultsController:searchResultsController]) {
}
return self;
}
#pragma mark - UISearchBar delegate method
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
//代理传递方法
if (_classSearchCtrlDelegate) {
[searchBar becomeFirstResponder];
[_classSearchCtrlDelegate didStartSearching];
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
if (_classSearchCtrlDelegate) {
[searchBar resignFirstResponder];
[_classSearchCtrlDelegate didTapCancelBtn];
}
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (_classSearchCtrlDelegate) {
[_classSearchCtrlDelegate didChangeSearchText:searchText];
}
}
#pragma mark - getter method
- (EOCClassSearchBar *)classSearchBar {
if (!_classSearchBar) {
_classSearchBar = [[EOCClassSearchBar alloc] initWithFrame:CGRectMake(0.f, 0.f, self.view.eoc_width, 44.f)];
_classSearchBar.delegate = self;
}
return _classSearchBar;
}
@end
EOCClassSearchBar:
.h里面没有什么东西,.m文件如下:
#import "EOCClassSearchBar.h"
@interface EOCClassSearchBar ()
@property(nonatomic, strong)UITextField *searchTextField;
@property(nonatomic, strong)UIButton *cancelBtn;
@property(nonatomic, strong)UIImageView *searchBarImageView;
@end
@implementation EOCClassSearchBar
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// 截取手势事件,避免当修改textfield的frame后,点击最左边的区域,也响应了事件
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
[self addGestureRecognizer:tapGesture];
}
return self;
}
- (void)tapAction
{
NSLog(@"%s", __func__);
}
//修改textfield的frame只能在layoutSubviews中
- (void)layoutSubviews {
[super layoutSubviews];
// 修改textfield的frame
self.searchTextField.frame = ({
CGRect frame = self.searchTextField.frame;
frame.origin.x = 60.f;
frame.size.width -= 60.f;
frame;
});
}
// 绘制搜索框
- (void)drawRect:(CGRect)rect {
self.barTintColor = [UIColor orangeColor];
self.tintColor = [UIColor redColor];
self.showsCancelButton = YES;
// self.barTintColor = EOCColor(240, 243, 245);
[self becomeFirstResponder];
UITextField *textField = self.searchTextField;
textField.placeholder = @"Search EightClock";
textField.font = [UIFont systemFontOfSize:12.f];
textField.backgroundColor = EOCColor(240, 243, 245);
textField.textColor = [UIColor greenColor];
textField.textAlignment = NSTextAlignmentLeft;
[self.cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
[self.cancelBtn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
//在搜索框的底部画一条绿线 画线条
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0.f, self.frame.size.height)];
[path addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height)];
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.path = path.CGPath;
shapeLayer.strokeColor = [UIColor greenColor].CGColor;
shapeLayer.lineWidth = 2.5f;
[self.layer addSublayer:shapeLayer];
}
- (void)btnAction:(UIButton *)btn {
self.searchTextField.text = @"";
// 调用代理,清空搜索内容
[self.delegate searchBar:self textDidChange:@""];
}
#pragma mark - getter method
- (UITextField *)searchTextField {
if (!_searchTextField) {
for (id view in [[self.subviews lastObject ]subviews]) {
if ([view isKindOfClass:NSClassFromString(@"UISearchBarTextField")]) {
_searchTextField = (UITextField *)view;
}
}
}
return _searchTextField;
}
- (UIButton *)cancelBtn {
if (!_cancelBtn) {
for (id view in [[self.subviews lastObject ]subviews]) {
if ([view isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
_cancelBtn = (UIButton *)view;
}
}
}
return _cancelBtn;
}
- (UIImageView *)searchBarImageView {
if (!_searchBarImageView) {
for (id view in [[self.subviews lastObject ]subviews]) {
if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
_searchBarImageView = (UIImageView *)view;
// _searchBarImageView.userInteractionEnabled = YES;
}
}
}
return _searchBarImageView;
}
@end
网友评论