zoukankan      html  css  js  c++  java
  • IOS开发之--NSPredicate

    我把常用的NSPredicate使用场景整理了一下
     
    Cocoa提供了一个NSPredicate的类, 指定过滤方式筛选数据。
     
    关于性能我做了个简单的测试,结果如下
     
    数据源500万条数据,计算时间基于5次试验的平均值

    检索数据条数 For循环时间(秒) NSPredicate时间(秒)
    1(位于数据源最后一项) 0.356625 1.487944
    1(位于数据源前1000项) 0.002461 1.516057
    6 1.763434 2.571393
    12 3.466698 3.43019
    24 6.58877 5.465602
    48 12.699893 9.312682
    96 25.36474 17.235685

    从以上测试结果看,苹果对predicate的确做了优化,这种优化随着搜索数据集合的增加逐渐显现出来,

    检索1条数据时,该数据在数据源中的位置对于Nspredicate来说基本没有影响;

    搜索100条数据比for循环节省8秒钟时间,

    但是搜索少量数据如1-10条以内的数据时,for循环还比较占优势  

    下面整理一下常用方法:

    NSPredicate有3种创建方式:格式化字符串/模板/代码方式,下面介绍3种方式

     1.     使用格式化字符串创建

    语法:NSPredicate *predicate = [NSPredicate predicateWithFormat: @"name == 'Herbie'"];
    这里的格式化字符串方式比较丰富,可以用到多种运算符:
     
    ·      比较和逻辑运算符
    ==和=、>、>=和=>、<、<=和=<、!=和<>

    AND、OR、NOT逻辑运算符或者C样式的等效表达式&&、||和!

    示例:
predicate=[NSPredicate predicateWithFormat:@"(engine.horsepower>50) AND (engine.horsepower<200)"];


    字符串中的运算符不区分大小写,你可以随意使用AnD、And或or,
    不等号既适用于数字值又适用于字符串值;
    另外注意表达式的写法支持KVC键路径
     
    ·      数组运算符
    BETWEEN:

    ü  predicate=[NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN {50,200}"];

    ü  NSArray *betweens=[NSArray arrayWithObjects:
    

                      [NSNumber numberWithInt:50],
                   

                      [NSNumber numberWithInt:200],nil];


       predicate=[NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN %@",betweens];

     ü  predicateTemplate=[NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN $POWERS"];


      varDict=[NSDictionary dictionaryWithObjectsAndKeys:betweens,@"POWERS",nil];


      predicate=[predicateTemplate predicateWithSubstitutionVariables:varDict];

    IN:
    	ü predicate=[NSPredicate predicateWithFormat:@"name IN {'Herbie','Snugs','Badger','Flap'}"];
        同理,IN也支持上面描述的between类型的构造方式
     
    ·      字符串运算符
     
        BEGINSWITH

        ENDSWITH

        CONTAINS

     ·      LIKE运算符

          通配符: ? 匹配单个字符 * 匹配任意个字符
    NSPredicate *predicate = [NSPredicate
    				predicateWithFormat:@"lastName like[c] "S*""];

     ·      正则表达式, MATCHES运算符

    NSString *match = @"imagexyz-\d{3}\.png"; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF matches %@", match];

     
    ·     SELF关键字 
     
    格式化字符串中除了使用对象的键路径引用属性,还可以使用
    SELF关键字引用对象本身
    predicate=[NSPredicate predicateWithFormat:@"SELF.name IN {'Herbie','Snugs','Badger','Flap'}"];
     
     ·    [c]、[d]或[cd]修饰符

         为了减少名称匹配规则,可以为这些运算符添加[c]、[d]或[cd]修饰符。其中,c表示“不区分大小写”,d表示“不区分发音符   号”,[cd]表示都不区分。

    例如 "name BEGINSWITH[cd] 'HERB'"

     ·      ALL,ANY关键字

        对象存在关系对象时,有时还会用到ALL,ANY,指明本对象内的xx数组某一个或所有的需要满足xx条件
        [NSPredicate predicateWithFormat:@"ANY entryTags IN %@", selectedTags];
        [NSPredicate predicateWithFormat:@"ALL entryTags IN %@", selectedTags];

     2.     使用Predicate 模板创建

         模板创建是基于字符串创建的,只不过提供了NSPredicate的模板实现方式
    如果使用CoreData,可以使用Xcode的设计工具为Fetchrequest添加Predicate模板,详情可参考https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdMOM.html#//apple_ref/doc/uid/TP40002328
    <632B09E1-5DB2-45E5-8A45-73E2B149B108.png>
     
    当然,Predicate模板不仅仅是为CoreData服务的,可以实现自己的模板:
    如上面的between运算符的第三种使用方式就是一种模板的实现
        NSArray *betweens = [NSArray arrayWithObjects:
                                [NSNumber numberWithInt: 50],
                                [NSNumber numberWithInt: 200], nil];
              NSPredicate* predicateTemplate = [NSPredicate predicateWithFormat: @"engine.horsepower BETWEEN $POWERS"];
               varDict = [NSDictionary dictionaryWithObjectsAndKeys: betweens, @"POWERS", nil];
              predicate = [predicateTemplate predicateWithSubstitutionVariables: varDict];

      模板创建NSPredicate主要用于同样的过滤方式,不同的源数据情况下重用NSPredicate的情况使用。

     3.     直接用代码创建

    这种方式是直接使用predicate 和 expression创建NSPredicate,优点是没有使用到字符串解析等大量繁杂的字符串拼接方式,缺点是需要构造大量的expression对象,如下官网给出的实例:
     
    NSExpression *lhs = [NSExpression expressionForKeyPath:@"revenue"];
     
    NSExpression *greaterThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:1000000]];
     
    NSPredicate *greaterThanPredicate = [NSComparisonPredicate
     
        predicateWithLeftExpression:lhs
     
        rightExpression:greaterThanRhs
     
        modifier:NSDirectPredicateModifier
     
        type:NSGreaterThanOrEqualToPredicateOperatorType
     
        options:0];
     
     
    NSExpression *lessThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:100000000]];
     
    NSPredicate *lessThanPredicate = [NSComparisonPredicate
     
        predicateWithLeftExpression:lhs
     
        rightExpression:lessThanRhs
     
        modifier:NSDirectPredicateModifier
     
        type:NSLessThanPredicateOperatorType
     
        options:0];
     
     
     
    NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
     
        @[greaterThanPredicate, lessThanPredicate]];

     感觉这种方式用起来不太方便,也不太灵活,所以不继续深究了

  • 相关阅读:
    eclipse 中文乱码
    为linux下ibus输入法添加搜狗词库
    汇编语言数据类型与声明
    linux下访问小米手机sd卡
    ubuntu linux下真机调试android程序
    Rhythmbox mp3音乐乱码的解决办法
    初学python线程(转)
    linux下安装安装BeautifulSoup
    django模板过滤器
    django使用静态文件
  • 原文地址:https://www.cnblogs.com/v-jing/p/3169081.html
Copyright © 2011-2022 走看看