大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处.

如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;)


以前iOS的搜索一般都使用UISearchDisplayController来完成,不过自从iOS 8.0开始,该控制器被标记为废弃,我们可以在iOS 8.0之后使用一个新的搜索控制器UISearchController来完成搜索.

本篇博文将介绍以上2种搜索控制器的简单用法,并比较它们的区别.Let’t Go!

UISearchDisplayController

使用该控制器我们必须给根控制器添加一个UISearchDisplayDelegate协议,然后完成其规定的几个回调方法:

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
                                shouldReloadTableForSearchString:(NSString *)searchString{
    [_filteredNames removeAllObjects];
    if (searchString.length > 0) {
        NSPredicate *predicate = [NSPredicate predicateWithBlock:
                                    ^BOOL(NSString *name,NSDictionary *b) {
            NSRange range = [name rangeOfString:searchString options:NSCaseInsensitiveSearch];
            return range.location != NSNotFound;
        }];
        for (NSString *key in _keys) {
            NSArray *matchs = [_names[key] filteredArrayUsingPredicate:predicate];
            [_filteredNames addObjectsFromArray:matchs];
        }
    }
    return YES;
}

-(void)searchDisplayController:(UISearchDisplayController *)controller
                                    didLoadSearchResultsTableView:(UITableView *)tableView{
    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:SectionsTableID];
}

其中第一个方法在搜索关键字发生改变时调用,后一个则在搜索表视图加载完毕后调用,我们可以看见如上代码所示,我们在搜索表视图加载后将其表视图的UITableViewCell元素的ID和一个特定的ID绑定,这样做可以重用已存在的单元格.另外需要注意的是该ID和根视图控制器中标示图的单元格ID是一样的,虽然这两个表视图是不一样的.

我们在根视图控制器的didLoadView中用以下代码初始化UISearchDisplayController:

UISearchBar *searchBar = [[UISearchBar      alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
tableView.tableHeaderView = searchBar;
_searchController = [[UISearchDisplayController alloc]initWithSearchBar:searchBar                                       contentsController:self];

_searchController.delegate = self;
_searchController.searchResultsDataSource = self;

以上代码首先创建一个searchBar并将其设置为tableView的表头视图,接着以该searchBar为参数创建UISearchDisplayController对象,最后设置好其对应的委托.

因为此时根视图中存在2个表视图,所以我们在处理相关回调方法时要区分当前处理的是哪张表视图:

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    if (tableView.tag == 1) {
        return _keys.count;
    }else{
        return 1;
    }
}

我们将默认的呈现数据的表视图的tag设置为1,这样我们就知道当前需要处理的是哪张表视图了.其它的回调与此类似,不再一一述及.

UISearchController

下面我们来看看iOS 8.0之后新的搜索器类的使用方法.首先我们也必须添加一个UISearchResultsUpdating协议,同时实现一个协议方法:

-(void)updateSearchResultsForSearchController:(UISearchController *)searchController;

该方法和前一个搜索器类的方法类似,不过要注意的是它不返回值,这意味着如果你想要显示搜索结果,你必须手动刷新表视图.下面给出一个该方法的例子:

-(void)updateSearchResultsForSearchController:(UISearchController *)searchController{
    NSString *searchString = _searchController.searchBar.text;
    [_filteredNames removeAllObjects];
    if (searchString.length > 0) {
        NSPredicate *predicate = [NSPredicate predicateWithBlock:
                                  ^BOOL(NSString *name,NSDictionary *b) {
                                      NSRange range = [name rangeOfString:searchString options:NSCaseInsensitiveSearch];
                                      return range.location != NSNotFound;
                                  }];
        for (NSString *key in _keys) {
            NSArray *matchs = [_names[key] filteredArrayUsingPredicate:predicate];
            [_filteredNames addObjectsFromArray:matchs];
        }
    }else{
        //如果搜索关键字为空则显示所有key
        for (NSString *key in _keys) {
            NSArray *matchs = _names[key];
            [_filteredNames addObjectsFromArray:matchs];
        }
    }
    UITableView *tableView = [self.view viewWithTag:1];
    //手动刷新表视图
    [tableView reloadData];
}

UISearchController还有一个和UISearchDisplayController不同的地方,就是判断当前表视图是否是搜索表视图的方法:

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    if (_searchController.active) {
        return 1;
    }else{
        return _keys.count;
    }
}

好吧,我收回上面的话…准确来说,应该是前者根本没有自己的表视图,它使用的表视图就是默认的表视图.也就是我们必须自默认的表视图中判断当前搜索是否激活,如果是则显示搜索后的结果,否则显示默认呈现的数据.

最后我们来看看,如何初始化UISearchController:

_searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
    _searchController.searchResultsUpdater = self;
    _searchController.dimsBackgroundDuringPresentation = NO;
    _searchController.hidesNavigationBarDuringPresentation = NO;
    tableView.tableHeaderView = _searchController.searchBar;

大家可以看到不用再自己创建UISearchBar对象了,UISearchDisplayController已经帮你搞定了.

总结

最后我们来看一下以上2种搜索控制器的不同:

  1. 前者使用单独的表视图,后者没有表视图,其内容使用默认的表视图来呈现.
  2. 前者需要手动创建UISearchBar对象,而后者不需要
  3. 前者需要在表示图的协议回调中判断当前是哪个表视图,而后者只是简单判断搜索是否处在激活状态
  4. 它们遵守的协议不一样,协议方法自然也不一样
  5. 前者比较复杂,后者更简单,从类的构成上来说也更合理.

iOS中的两种搜索方式UISearchDisplayController和UISearchController的更多相关文章

  1. iOS中的两种主要架构及其优缺点浅析

    凡是程序的开发者,应该对程序的架构都不陌生.一个程序的架构的好坏对这个程序有着非常重要的作用.今天我们来看一下iOS开发中用要的两种主流的程序架构.这个过程中我们主要以例子的形式展开. 我们来看第一种 ...

  2. Javaweb学习笔记——(六)——————xml中jaxp两种解析方式和dom4j运用

    1.xml的scheam约束 dtd的语法:<!ElEMENT 元素名称 约束> **schema符合xml的语法,xml语句 **一个xml中可以有多个schema,多个schema使用 ...

  3. javascript中对象两种创建方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. String中的两种实例化方式的区别

    直接赋值:(String str = "字符串");只会开辟一块堆内存空间,并且会自动保存在对象池中以供下次重复使用. 构造方法:(String str = new  String ...

  5. web 开发之js---ajax 中的两种提交方式ajax post 和 ajax get 实例

    ()post http://04101334.iteye.com/blog/637695/ ()get function serializeElement(element) { var method ...

  6. class类名在webpack项目中的两种引用方式

    一.问题描述 在项目工程中,我们通常既用到css module,也用到普通的less文件引用方式,代码及webpack配置如下,运行时,发现只有css module起作用,如何让两者都起作用呢? // ...

  7. Hibeernate中的两种分页方式

    1. return getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(S ...

  8. ios中的界面跳转方式

    ios中,两种界面跳转方式 1.NavgationController本身可以作为普通ViewController的容器,它有装Controller的栈,所以可以push和pop它们,实现你所说的跳转 ...

  9. hibernate 一对一 one to one的两种配置方式

    hibernate中one-to-one两种配置方式 标签: hibernateHibernateone-to-one 2013-02-19 17:44 11445人阅读 评论(1) 收藏 举报  分 ...

随机推荐

  1. 51nod 1686 第k大区间

    1686 第K大区间 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. ...

  2. 例10-5 uva12716

    题意:gcd(a,b) = a^b,( 1≤ a , b ≤ n) 思路: ① a^b = c, 所以 a^c = b,而且c是a的约数,枚举a,c,再gcd判断 ② 打表可知 a-b = c,而且a ...

  3. POJ 1324(BFS + 状态压缩)

    题意:给你一条蛇,要求一以最少的步数走到1,1 思路: 最开始一直没想到应该怎样保存状态,后来发现别人用二进制保存蛇的状态,即每两个节点之间的方向和头节点,二进制最多14位(感觉状态保存都能扯到二进制 ...

  4. 《Java技术》第一次作业

    (一)学习总结 1.在java中通过Scanner类完成控制台的输入,查阅JDK帮助文档,Scanner类实现基本数据输入的方法是什么?不能只用文字描述,一定要写代码,通过具体实例加以说明. (1)使 ...

  5. python2.7入门---内置函数

        内置函数     abs() divmod() input() open() staticmethod() all() enumerate() int() ord() str() any() ...

  6. C程序练习

    1.编程从键盘任意输入两个时间(例如4时55分和1时25分),计算并输出这两个时间之间的间隔.要求不输出时间差的负号. #include<stdio.h> int main() { int ...

  7. android 欢迎界面的制作

    再打开手机app的时候,最先映入我们眼帘的是一个覆盖手机全屏的欢迎界面,在这个界面显示出来的时候整个手机屏幕只会显示这一个界面,上面的标题栏,以及手机最顶端的状态栏都会消失,只有欢迎页面结束跳转到其他 ...

  8. 关于Allele(等位基因)的理解

    高中学生物的时候关于遗传学的部分,记得当时的教材上为了简化处理一般将基因型定义为AA, Aa, aa.其实这种抽象的理解对应付高考是很有用的,但是实际应用中如果还这样理解那么便会产生一些疑问.之所以会 ...

  9. miracl去除某些特殊信息

    只需要在mirdef.h中增加定义 #define MR_STRIPPED_DOWN  即可在编译的时候,去掉错误信息 #define MIRACL 32 #define MR_LITTLE_ENDI ...

  10. Swift基础之CoreData的使用

    以前使用过OC版本的CoreData应该很好理解Swift方式,所以这里简单的展示一下,增删改查的方法使用,同时给大家说一下创建步骤,方便大家的使用,转载请注明出处,谢谢~ 步骤一:创建一个Swift ...