自己实现 UITableView 搜索,相对于使用 UISearchDisplayController 来说自己写稍微麻烦了那么一点点,但是更加灵活。主要就是用一个字段区分出当前是搜索还是非搜索,然后 reload 相应的 data 就行了,和 UISearchDisplayController 的实现也很像,不过 UISearchDisplayController是两个 tableview 切换,这里我们是一个 tableview load 不同的数据。
关键代码:
@interface MainTableViewController : UIViewController<UISearchBarDelegate,UITableViewDelegate,UITableViewDataSource>{ UITableView *mytableView; NSArray *data; NSMutableArray *filterData; BOOL isFiltered; // 标识是否正在搜素 UIView *mask; }
- (void)viewDidLoad { [super viewDidLoad]; mytableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height-20)]; mytableView.dataSource = self; mytableView.delegate = self; [self.view addSubview:mytableView]; UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width , 44)]; searchBar.placeholder = @"搜索"; searchBar.delegate = self; mytableView.tableHeaderView = searchBar; // 添加一层 mask mask = [[UIView alloc] initWithFrame:CGRectMake(0, 20 + 44, self.view.frame.size.width, self.view.frame.size.height -20 -44)]; [self.view addSubview:mask]; mask.backgroundColor = [UIColor blackColor]; mask.alpha = 0; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // 通过 isFiltered 区分出当前显示的是搜索结果集还是原结果集 if (isFiltered) { return filterData.count; } return data.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellid = @"cellid"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid]; if (cell==nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid]; } // 通过 isFiltered 区分出当前显示的是搜索结果集还是原结果集 if (isFiltered) { cell.textLabel.text = filterData[indexPath.row]; }else{ cell.textLabel.text = data[indexPath.row]; } return cell; } - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{ // 开始搜索时弹出 mask 并禁止 tableview 点击 NSLog(@"searchBarTextDidBeginEditing"); isFiltered = YES; searchBar.showsCancelButton = YES; mask.alpha = 0.3; mytableView.allowsSelection = NO; mytableView.scrollEnabled = NO; } - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{ NSLog(@"searchBarTextDidEndEditing"); } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{ NSLog(@"textDidChange"); if (searchText.length == 0) { isFiltered = NO; mask.alpha = 0.3; mytableView.allowsSelection = NO; mytableView.scrollEnabled = NO; [mytableView reloadData]; return; } isFiltered = YES; mask.alpha = 0; mytableView.allowsSelection = YES; mytableView.scrollEnabled = YES; // 谓词搜索 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self contains [cd] %@",searchText]; filterData = [[NSMutableArray alloc] initWithArray:[data filteredArrayUsingPredicate:predicate]]; [mytableView reloadData]; } - (void)searchBarCancelButtonClicked:(UISearchBar *) sb{ // 点击 cancel 时去掉 mask ,reloadData sb.text = @""; [sb setShowsCancelButton:NO animated:YES]; mytableView.allowsSelection = YES; mytableView.scrollEnabled = YES; [sb resignFirstResponder]; mask.alpha = 0; isFiltered = NO; [mytableView reloadData]; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *text; if (isFiltered) { text = filterData[indexPath.row]; }else{ text = data[indexPath.row]; } NSLog(@"you click index:%d %@",indexPath.row,text); }
基于 ios7.1 布局写了一个 demo: http://pan.baidu.com/s/1ntn0MeP