iOS新手入门常见问题5-UITableViewController添加列表上的搜索栏
本篇说的是利用UISearchController实现UITableViewController顶部的搜索功能。
自从iOS8以后, 苹果官方已经推荐我们使用UISearchController来代替UISearchBar+UISearchDisplayController的组合方式了,同时协议也要更变为UISearchResultsUpdating了。
声明UISearchController对象及协议
@interface ViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating>
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) NSArray *searchResultList;
@property (nonatomic, strong) NSArray *originalList;
@end
上面的代码完成了指定协议和增加变量的功能
初始化UISearchController对象
下面需要自己初始化一下UISearchController ,一般在viewDidLoad方法中完成
// 参数传递为nil,表示使用当前自身ViewController作为搜索结果显示的界面
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
添加UISearchResultsUpdating协议实现的方法
初始化并太添加给tableView的头布局之后,接下来就要实现UISearchResultsUpdating中声明的协议了。 协议中方法只有一个:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = [self.searchController.searchBar text];
NSPredicate *preicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", searchString];
if (self.searchResultList!= nil) {
[self.searchResultList removeAllObjects];
}
// 从原始数据中筛选数据
self.searchResultList= [NSMutableArray arrayWithArray:[self.originalList filteredArrayUsingPredicate:preicate]];
// 刷新表格
[self.tableView reloadData];
}
上面协议方法中用到了一个叫做NSPredicate的东西,实现类似sql语句的功能,详细内容自行网络获取吧。
让UITabeleView显示搜索后的数据
通过协议方法筛选得到新的数据list之后,画面上UITableViewController上要显示的行数以及每行显示数据都要发生改变了。 可以通过searchController.active进行判断当前是显示着原始数据还是搜素结果的数据:
下面就利用这个属性来重新修改一下UITableViewController相关的协议方法。
// 设置区域要显示的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (self.searchController.active) {
return [self.searchResultList.count];
} else {
return [self.originalList.count];
}
}
// 返回每行单元格的内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *id = @"CellID";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:id];
if (cell == nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:id];
}
if (self.searchController.active) {
// get data using self.searchResultList[indexPath.row];
} else {
// get data using self.originalList[indexPath.row];
}
return cell;
}
如果有点击每个单元格后进入下一个详细画面的转场,还要在- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender方法中修改要传递给目标画面的数据。
TableView搜索栏转场到下一画面后仍显示
最后,会发现一个问题,就是点击单元格转场到下一个画面后,下一个画面还会显示着前一个画面的搜索栏以及输入法。这时需要在前一个画面(UITableViewController)的viewWillDisappear方法中添加对searchBar进行remove的逻辑处理。
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (self.searchController.active) {
self.searchController.active = NO;
[self.searchController.searchBar removeFromSuperview];
}
}