曾几何时,使用过UISearchBar,当时看到UISearchDisplayController简直是一头雾水,不知道怎么使用。最近的一个app中需要使用该功能,于是写了个Demo探究下。现在做下笔记。
首先往故事板中视图控制器中加入一个Search Bar and Search Display组件:
然后连接Outlets,包括搜索栏和SearchDisplayController:
在ViewController中声明它要遵守以下委托:
@interface ViewController () <UISearchBarDelegate,UISearchDisplayDelegate,UITableViewDelegate,UITableViewDataSource>
@property (strong, nonatomic) NSMutableArray *storeResults;
@property (strong, nonatomic) NSMutableArray *results;
初始化工作包括设置委托和初始化数组,代码如下:
- (void)viewDidLoad
{
[super viewDidLoad];
_srcTableView.dataSource = self;
_srcTableView.delegate = self;
_searchBar.delegate = self;
_mySearchDisplayController.searchResultsDataSource = self;
_mySearchDisplayController.searchResultsDelegate = self;
_mySearchDisplayController.delegate = self;
self.storeResults = [NSMutableArray arrayWithObjects:@"广州", @"北京", @"上海", @"深圳", @"香港", @"广东", @"北师大", @"北大", @"香江", @"香菜", @"北海道", @"惠州", @"东莞", @"杭州", nil];
self.results = [NSMutableArray array];
}
接下来实现UISearchDisplayDelegate中的方法:
#pragma mark - UISearchDisplayDelegate
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString
scope:[_searchBar scopeButtonTitles][_searchBar.selectedScopeButtonIndex]];
return YES;
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForSearchText:_searchBar.text
scope:_searchBar.scopeButtonTitles[searchOption]];
return YES;
}
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
NSMutableArray *tempResults = [NSMutableArray array];
NSUInteger searchOptions = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch;
for (int i = 0; i < _storeResults.count; i++) {
NSString *storeString = _storeResults[i];
NSRange storeRange = NSMakeRange(0, storeString.length);
NSRange foundRange = [storeString rangeOfString:searchText options:searchOptions range:storeRange];
if (foundRange.length) {
[tempResults addObject:storeString];
}
}
[self.results removeAllObjects];
[self.results addObjectsFromArray:tempResults];
}
这几个方法用于实现搜索功能,匹配的规则是:源字符串内容是否包含或等于要搜索的字符串内容。
在搜索结果出来后,我们将其存储在results数组中,接下来实现表格的委托方法来展示搜索结果:
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == _mySearchDisplayController.searchResultsTableView) {
return _results.count;
}
else {
return _storeResults.count;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier];
}
if (tableView == _mySearchDisplayController.searchResultsTableView) {
cell.textLabel.text = _results[indexPath.row];
}
else {
cell.textLabel.text = _storeResults[indexPath.row];
}
return cell;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == _mySearchDisplayController.searchResultsTableView) {
NSLog(@"%@", _results[indexPath.row]);
}
else {
NSLog(@"%@", _storeResults[indexPath.row]);
}
}
为了区分正在展示的表格内容是搜索结果还是源数据,先要进行tableView == _mySearchDisplayController.searchResultsTableView的判断。
运行结果如下:
简单总结下,使用UISearchDisplayController显示搜索结果的几个步骤:
1.准备源数据(搜索的参照数据)
2.在故事板中加入Search Bar and Search Display组件
3.设置Search Bar和Search Display的Delegate
4.实现UISearchDisplayDelegate的方法,搜索的匹配工作在这里完成。搜索完毕后,将搜索结果存储起来。
5.实现UITableViewDataSource和UITableViewDelegate的方法,展示搜索结果。
当然委托中还有许许多多的方法没有实现,这里只是实现了基本的搜索功能,更多功能有待日后继续探究。
Demo 已经上传,可以参照着看下本文。