UISearchController的使用
前言
在iOS 8.0以上版本中,我们可以使用UISearchController来非常方便地在UITableView中添加搜索框。而在iOS8.0之前版本中,我们还是必须使用UISearchBar + UISearchDisplayController的组合方式。
1. 添加UISearchController属性
@property(strong, nonatomic) UISearchController *searchController;
@property(strong, nonatomic) NSMutableArray *allCities; // 所有城市
@property(strong, nonatomic) NSMutableArray *filteredCities; // 根据searchController搜索的城市
2. 初始化UISearchController
使用懒加载或者在viewDidLoad中初始化UISearchController
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = false;
[self.searchController.searchBar sizeToFit];
self.searchController.searchBar.backgroundColor = UIColorFromHex(0xdcdcdc);
self.tableView.tableHeaderView = self.searchController.searchBar;
3. UISearchResultsUpdating协议
使用UISearchController要继承UISearchResultsUpdating协议,实现其中的UISearchResultsUpdating方法。
#pragma mark - searchController delegate
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
[self.filteredCities removeAllObjects];
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", self.searchController.searchBar.text];
self.filteredCities = [[self.allCities filteredArrayUsingPredicate:searchPredicate] mutableCopy];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
UISearchController的searchBar中的内容一旦发生变化,就会调用该方法。在其中,我们可以使用NSPredicate来设置搜索过滤的条件。
4. 更新UITableView数据
引入UISearchController之后,UITableView的内容也要做相应地变动,即cell中要呈现的内容是allCities,还是filteredCities。这一点,可以通过UISearchController的active属性来判断,即判断输入框是否处于active状态。
UITableView相关的很多方法都要根据active来做判断:
#pragma mark - tableView delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (!self.searchController.active) {
return self.cityKeys.count;
} else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (!self.searchController.active) {
NSString *key = self.cityKeys[section];
NSArray *citySection = self.cityDict[key];
return citySection.count;
} else {
return self.filteredCities.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// 根据UISearchController的active属性来判断cell中的内容
if (!self.searchController.active) {
NSString *key = self.cityKeys[indexPath.section];
cell.textLabel.text = [self.cityDict[key] objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = self.filteredCities[indexPath.row];
}
return cell;
}
5. UISearchController的移除
在viewWillDisappear中要将UISearchController移除,否则切换到下一个View中,搜索框仍然会有短暂的存在。
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (self.searchController.active) {
self.searchController.active = NO;
[self.searchController.searchBar removeFromSuperview];
}
}
6. 其他属性修改
6.1 去除SearchBar默认灰色的背景颜色
在iOS7.0之前,UISearchBar视图里直接包含UISearchBarBackground和UISearchBarTextField两个视图,在iOS7.0及之后,UISearchBar视图里包含的是一个UIView视图,UIView视图里才是 UISearchBarBackground和UISearchBarTextField两个视图。
经多次试验,发现去除UISearchbar视图里的 UISearchBarBackground后UISearchBar的背景就透明了,代码如下:
for ( UIView *view in self.searchBar.subviews ) {
// for before iOS7.0
if ( [view isKindOfClass:NSClassFromString(@"UISearchBarBackground")] ) {
[view removeFromSuperview];
break;
}
// for later iOS7.0(include)
if ( [view isKindOfClass:NSClassFromString(@"UIView")] && view.subviews.count>0 ) {
[[view.subviews objectAtIndex:0] removeFromSuperview];
break;
}
}
6.2 改变SearchController取消按钮
_searchController.searchBar.showsCancelButton = YES;
for(UIView *view in [searchController.searchBar subviews]) {
for (UIView *subView in [view subviews]) {
if([subView isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)subView;
[btn setTitle:@"取消" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
}
}
}