UISearchDisplayController

转在于 :http://www.cnblogs.com/lesliefang/p/3929677.html

UISearchDisplayController 是苹果专为 UITableView 搜索封装的一个类。

里面内置了一个 UITableView 用于显示搜索的结果。它可以和一个需要搜索功能的

controller 关联起来,其它的像原 TableView 和搜索结果 TableView 的切换, mask 的显示等等都

封装好了,使用起来非常非常的简单。特别是要实现全屏搜索时使用最多。

全屏搜索的意思是如果你用了  NavigationBar 当点击搜索框时 TableView 会自动弹上去覆盖

NavigationBar,达到一种全屏搜索的效果,这一切 UISearchDisplayController 都封装好了,如果自己

写就比较麻烦一些。

关键代码:

@interface MainViewController : UITableViewController{
    NSArray *data;
    NSArray *filterData;
    UISearchDisplayController *searchDisplayController;
}
复制代码
- (void)viewDidLoad
{
    [super viewDidLoad];
    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width
                                                                           , 44)];
    searchBar.placeholder = @"搜索";
    
    // 添加 searchbar 到 headerview
    self.tableView.tableHeaderView = searchBar;
    
    // 用 searchbar 初始化 SearchDisplayController
    // 并把 searchDisplayController 和当前 controller 关联起来
    searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    
    // searchResultsDataSource 就是 UITableViewDataSource
    searchDisplayController.searchResultsDataSource = self;
    // searchResultsDelegate 就是 UITableViewDelegate
    searchDisplayController.searchResultsDelegate = self;
}
复制代码
复制代码
/*
 * 如果原 TableView 和 SearchDisplayController 中的 TableView 的 delete 指向同一个对象
 * 需要在回调中区分出当前是哪个 TableView
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.tableView) {
        return data.count;
    }else{
        // 谓词搜索
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self contains [cd] %@",searchDisplayController.searchBar.text];
        filterData =  [[NSArray alloc] initWithArray:[data filteredArrayUsingPredicate:predicate]];
        return filterData.count;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellId = @"mycell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
    }
    
    if (tableView == self.tableView) {
        cell.textLabel.text = data[indexPath.row];
    }else{
        cell.textLabel.text = filterData[indexPath.row];
    }
    
    return cell;
}
复制代码

DEMO 下载:http://pan.baidu.com/s/1pJ8vvC3


新的搜索功能实现

iOS 8以后,苹果推荐使用UISearchController,如果在初始化的时候,没有设置searchResultsController,那么搜索结果就在代理对象控制器的表格中显示。

    _searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
    _searchController.searchResultsUpdater = self;
    // 默认为YES,控制搜索控制器的灰色半透明效果
    //    _searchController.dimsBackgroundDuringPresentation = NO;
    // 默认为YES,控制搜索时,是否隐藏导航栏
    //    _searchController.hidesNavigationBarDuringPresentation = NO;
    _searchController.searchBar.delegate = self;
    _searchController.searchBar.placeholder = @"请输入...";
    _searchController.searchBar.tintColor = [UIColor orangeColor];
    _searchController.searchBar.barTintColor = [UIColor greenColor];
    [_searchController.searchBar sizeToFit];

    self.definesPresentationContext = YES;

    self.tableView.tableHeaderView = _searchController.searchBar;

    self.tableView.tableFooterView = [UIView new];
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

接下来也是实现代理方法:

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
    [self.searchArray removeAllObjects];
    //执行搜索操作
    NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"self contains[cd] %@",_searchController.searchBar.text];
    self.searchArray = [[self.titles filteredArrayUsingPredicate:searchPredicate] mutableCopy];
    //刷新表格
    [self.tableView reloadData];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

因为搜索结果和正常情况使用的是同一个tableView,那么如何区分搜索时显示搜索的数据源呢? 
通过UISearchController的active属性即可判断,这是一个BOOL类型的属性。 
示例代码:

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (_searchController.active) {
        return self.searchArray.count;
    }
    return self.titles.count;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

其实到这里,表格头部的搜索功能就完成了。

下面还有一些可能出现的Bug或场景解决方案。

1.如果我不需要实时显示搜索结果怎么处理?

显然,如果我们搜索功能的结果需要服务器返回,那么就不应该在用户输入每个字母的时候都去请求一次。应该是用户输入完关键字,点击搜索后再去搜索。 
那么这时,就需要先实现UISearchBar 的UISearchBarDelegate中的代理方法:

#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    [self.searchArray removeAllObjects];
    //执行搜索操作
    NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"self contains[cd] %@",_searchController.searchBar.text];
    self.searchArray = [[self.titles filteredArrayUsingPredicate:searchPredicate] mutableCopy];
    //刷新表格
    [self.tableView reloadData];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后,还必须实现的UISearchControllerUISearchResultsUpdating中的代理方法:

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
    //刷新表格
    [self.tableView reloadData];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

可以看一下上面这个代理方法的注释:

// Called when the search bar's text or scope has changed or when the search bar becomes first responder.
当搜索框中的内容,范围发生变化,或者搜索框成为或者取消第一响应者时,会被调用。
 
 
  • 1
  • 2

所以需要在这里刷新一下tableView 来更新数据源,因为他们用的是同一个tableView展示数据。 
怎么证明呢? 
很简单,只需要在tableView 的数据源方法中打印一下tableView,看他们是否是同一个TableView对象即可。

// 正常情况下的tableView
<UITableView: 0x7f86aa113000; frame = (0 0; 320 504); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600000241c20>; layer = <CALayer: 0x6000000354c0>; contentOffset: {0, 0}; contentSize: {320, 0}>

// 搜索输入框被激活时的tableView
<UITableView: 0x7f86aa113000; frame = (0 0; 375 603); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600000241c20>; layer = <CALayer: 0x6000000354c0>; contentOffset: {0, 0}; contentSize: {375, 3344}>

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.设置搜索栏背景色

直接上代码了:

    _searchController.searchBar.barTintColor = [UIColor greenColor];
 
 
  • 1

当然,在以前的实现方式里,也可以直接设置searchBar的barTintColor来修改搜索栏的背景色。(这个属性是iOS 7之后加的)

3.改变搜索栏 “取消”按钮和 光标的颜色

还是直接上代码:

_searchController.searchBar.tintColor = [UIColor orangeColor];
 
 
  • 1

4.使用UISearchController如何在搜索时将搜索栏移动到导航栏上

这个问题的解决方案需要设置两个地方: 
第一,确保UISearchController 的hidesNavigationBarDuringPresentation为YES(这个属性默认就是YES,你要确定你没修改过这个属性)。 
第二,将当前控制器的definesPresentationContext设置为YES。即:

self.definesPresentationContext = YES;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值