zoukankan      html  css  js  c++  java
  • NSPredicate的

    转自 http://www.cocoachina.com/industry/20140321/8024.html

     NSPredicate是一个Foundation类,它指定数据被获取或者过滤的方式。它的查询语言就像SQL的WHERE和正则表达式的交叉一样,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。

     
    相比较抽象的谈论它,展示NSPredicate的使用方法更加容易,所以我们来重新审视NSSortDescriptor中使用的示例数据集吧:
     
    索引 1 2 3 4
    Alice Bob Charlie Quentin
    Smith Jones Smith Alberts
    年龄 24 27 33 31
     
    1. @interface Person : NSObject 
    2. @property NSString *firstName; 
    3. @property NSString *lastName; 
    4. @property NSNumber *age; 
    5. @end 
    6.  
    7. @implementation Person 
    8.  
    9. - (NSString *)description { 
    10.     return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; 
    11.  
    12. @end 
    13.  
    14. #pragma mark - 
    15.  
    16. NSArray *firstNames = @[ @"Alice", @"Bob", @"Charlie", @"Quentin" ]; 
    17. NSArray *lastNames = @[ @"Smith", @"Jones", @"Smith", @"Alberts" ]; 
    18. NSArray *ages = @[ @24, @27, @33, @31 ]; 
    19.  
    20. NSMutableArray *people = [NSMutableArray array]; 
    21. [firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
    22.     Person *person = [[Person alloc] init]; 
    23.     person.firstName = firstNames[idx]; 
    24.     person.lastName = lastNames[idx]; 
    25.     person.age = ages[idx]; 
    26.     [people addObject:person]; 
    27. }]; 
    28.  
    29. NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"firstName = 'Bob'"]; 
    30. NSPredicate *smithPredicate = [NSPredicate predicateWithFormat:@"lastName = %@", @"Smith"]; 
    31. NSPredicate *thirtiesPredicate = [NSPredicate predicateWithFormat:@"age >= 30"]; 
    32.  
    33. // ["Bob Jones"] 
    34. NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:bobPredicate]); 
    35.  
    36. // ["Alice Smith", "Charlie Smith"] 
    37. NSLog(@"Smiths: %@", [people filteredArrayUsingPredicate:smithPredicate]); 
    38.  
    39. // ["Charlie Smith", "Quentin Alberts"] 
    40. NSLog(@"30's: %@", [people filteredArrayUsingPredicate:thirtiesPredicate]); 
     
    集合中使用NSPredicate
    Foundation提供使用谓词(predicate)来过滤NSArray/NSMutableArray&NSSet/NSMutableSet的方法。
     
    不可变的集合,NSArray&NSSet,有可以通过评估接收到的predicate来返回一个不可变集合的方法filteredArrayUsingPredicate:和filteredSetUsingPredicate:。
     
    可变集合,NSMutableArray&NSMutableSet,可以使用方法filterUsingPredicate:,它可以通过运行接收到的谓词来移除评估结果为FALSE的对象。
     
    NSDictionary可以用谓词来过滤它的键和值(两者都为NSArray对象)。NSOrderedSet可以由过滤的NSArray或 NSSet生成一个新的有序的集,或者NSMutableSet可以简单的removeObjectsInArray:,来传递通过否定 predicate过滤的对象。
     
    Core Data中使用NSPredicate
    NSFetchRequest有一个predicate属性,它可以指定管理对象应该被获取的逻辑条件。谓词的使用规则在这里同样适用,唯一的 区别在于,在管理对象环境中,谓词由持久化存储助理(persistent store coordinator)评估,而不像集合那样在内存中被过滤。
     
    谓词语法
    替换
    %@是对值为字符串,数字或者日期的对象的替换值。
    %K是key path的替换值。
    1. NSPredicate *ageIs33Predicate = [NSPredicate predicateWithFormat:@"%K = %@", @"age", @33]; 
    2.  
    3. // ["Charlie Smith"] 
    4. NSLog(@"Age 33: %@", [people filteredArrayUsingPredicate:ageIs33Predicate]); 
    $VARIABLE_NAME是可以被NSPredicate -predicateWithSubstitutionVariables:替换的值。
    1. NSPredicate *namesBeginningWithLetterPredicate = [NSPredicate predicateWithFormat:@"(firstName BEGINSWITH[cd] $letter) OR (lastName BEGINSWITH[cd] $letter)"]; 
    2.  
    3. // ["Alice Smith", "Quentin Alberts"] 
    4. NSLog(@"'A' Names: %@", [people filteredArrayUsingPredicate:[namesBeginningWithLetterPredicate predicateWithSubstitutionVariables:@{@"letter": @"A"}]]); 
     
    基本比较
    =, ==:左边的表达式和右边的表达式相等。
    >=, =>:左边的表达式大于或者等于右边的表达式。
    <=, =<:左边的表达式小于等于右边的表达式。
    >:左边的表达式大于右边的表达式。
    <:左边的表达式小于右边的表达式。
    !=, <>:左边的表达式不等于右边的表达式。
     
    BETWEEN:左边的表达式等于右边的表达式的值或者介于它们之间。右边是一个有两个指定上限和下限的数值的数列(指定顺序的数列)。比如,1 BETWEEN { 0 , 33 },或者$INPUT BETWEEN { $LOWER, $UPPER }。
     
    基本复合谓词
    AND, &&:逻辑与.
    OR, ||:逻辑或.
    NOT, !:逻辑非.
     
    字符串比较
    字符串比较在默认的情况下是区分大小写和音调的。你可以在方括号中用关键字符c和d来修改操作符以相应的指定不区分大小写和变音符号,比如firstname BEGINSWITH[cd] $FIRST_NAME。
    BEGINSWITH:左边的表达式以右边的表达式作为开始。
    CONTAINS:左边的表达式包含右边的表达式。
    ENDSWITH:左边的表达式以右边的表达式作为结束。
    LIKE:左边的表达式等于右边的表达式:?和*可作为通配符,其中?匹配1个字符,*匹配0个或者多个字符。
    MATCHES:左边的表达式根据ICU v3(更多内容请查看ICU User Guide for Regular Expressions)的regex风格比较,等于右边的表达式。
     
    合计操作
    关系操作
    ANY,SOME:指定下列表达式中的任意元素。比如,ANY children.age < 18。
    ALL:指定下列表达式中的所有元素。比如,ALL children.age < 18。
    NONE:指定下列表达式中没有的元素。比如,NONE children.age < 18。它在逻辑上等于NOT (ANY ...)。
    IN:等于SQL的IN操作,左边的表达必须出现在右边指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' }。
     
    数组操作
    array[index]:指定数组中特定索引处的元素。
    array[FIRST]:指定数组中的第一个元素。
    array[LAST]:指定数组中的最后一个元素。
    array[SIZE]:指定数组的大小。
     
    布尔值谓词
    TRUEPREDICATE:结果始终为真的谓词。
    FALSEPREDICATE:结果始终为假的谓词。
     
    NSCompoundPredicate
    我们见过与&或被用在谓词格式字符串中以创建复合谓词。然而,我们也可以用NSCompoundPredicate来完成同样的工作。
     
    例如,下列谓词是相等的:
    1. [NSCompoundPredicate andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"age > 25"], [NSPredicate predicateWithFormat:@"firstName = %@", @"Quentin"]]]; 
    2.  
    3. [NSPredicate predicateWithFormat:@"(age > 25) AND (firstName = %@)", @"Quentin"]; 
    虽然语法字符串文字更加容易输入,但是在有的时候,你需要结合现有的谓词。在那些情况下,你可以使用NSCompoundPredicate -andPredicateWithSubpredicates:&-orPredicateWithSubpredicates:。
     
    NSComparisonPredicate
    同样的,如果你在读过上周的文章之后发现你使用了太多的NSExpression的话,NSComparisonPredicate可以帮助你解决这个问题。
     
    就像NSCompoundPredicate一样,NSComparisonPredicate从子部件构建了一个NSPredicate-- 在这种情况下,左侧和右侧都是NSExpression。 分析它的类的构造函数可以让我们一窥NSPredicate的格式字符串是如何解析的:
    1. + (NSPredicate *)predicateWithLeftExpression:(NSExpression *)lhs 
    2.                              rightExpression:(NSExpression *)rhs 
    3.                                     modifier:(NSComparisonPredicateModifier)modifier 
    4.                                         type:(NSPredicateOperatorType)type 
    5.                                      options:(NSUInteger)options 

    参数
    lhs:左边的表达式。
    rhs:右边的表达式。
    modifier:应用的修改符。(ANY或者ALL)
    type:谓词运算符类型。
    options:要应用的选项。没有选项的话则为0。
     
    NSComparisonPredicate类型
    1. enum { 
    2.    NSLessThanPredicateOperatorType = 0, 
    3.    NSLessThanOrEqualToPredicateOperatorType, 
    4.    NSGreaterThanPredicateOperatorType, 
    5.    NSGreaterThanOrEqualToPredicateOperatorType, 
    6.    NSEqualToPredicateOperatorType, 
    7.    NSNotEqualToPredicateOperatorType, 
    8.    NSMatchesPredicateOperatorType, 
    9.    NSLikePredicateOperatorType, 
    10.    NSBeginsWithPredicateOperatorType, 
    11.    NSEndsWithPredicateOperatorType, 
    12.    NSInPredicateOperatorType, 
    13.    NSCustomSelectorPredicateOperatorType, 
    14.    NSContainsPredicateOperatorType, 
    15.    NSBetweenPredicateOperatorType 
    16. }; 
    17. typedef NSUInteger NSPredicateOperatorType; 

    NSComparisonPredicate选项
    NSCaseInsensitivePredicateOption:不区分大小写的谓词。你通过在谓词格式字符串中加入后面带有[c]的字符串操作(比如,"NeXT" like[c] "next")来表达这一选项。
     
    NSDiacriticInsensitivePredicateOption:忽视发音符号的谓词。你通过在谓词格式字符串中加入后面带有[d]的字符串操作(比如,"naïve" like[d] "naive")来表达这一选项。
     
    NSNormalizedPredicateOption: 表示待比较的字符串已经被预处理了。这一选项取代了NSCaseInsensitivePredicateOption和 NSDiacriticInsensitivePredicateOption,旨在用作性能优化的选项。你可以通过在谓词格式字符串中加入后面带有 [n]的字符串(比如,"WXYZlan" matches[n] ".lan")来表达这一选项。
     
    NSLocaleSensitivePredicateOption: 表明要使用<,<=,=,=>,> 作为比较的字符串应该使用区域识别的方式处理。你可以通过在<,<=,=,=>,>其中之一的操作符后加入[l](比 如,"straße" >[l] "strasse")以便在谓词格式字符串表达这一选项。
     
    Block谓词
     
    最后,如果你实在不愿意学习NSPredicate的格式语法,你也可以学学NSPredicate +predicateWithBlock:。
    1. NSPredicate *shortNamePredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { 
    2.             return [[evaluatedObject firstName] length] <= 5; 
    3.         }]; 
    4.  
    5. // ["Alice Smith", "Bob Jones"] 
    6. NSLog(@"Short Names: %@", [people filteredArrayUsingPredicate:shortNamePredicate]); 
    ...好吧,虽然使用predicateWithBlock:是懒人的做法,但它也并不是一无是处。
     
    事实上,因为block可以封装任意的计算,所以有一个查询类是无法以NSPredicate格式字符串形式来表达的(比如对运行时被动态计算 的值的评估)。而且当同一件事情可以用NSExpression结合自定义选择器来完成时,block为完成工作提供了一个方便的接口。
     
    重要提示:由predicateWithBlock:生成的NSPredicate不能用于由SQLite存储库支持的Core Data数据的提取要求。
     
    我知道我已经说过很多次了,可是NSPredicate真的是Cocoa的优势之一。其他语言的第三方库如果能有它一半的能力就已经很幸运了--更别提标准库了。对于我们这些应用和框架开发者来说,有它作为标准组件使得我们在处理数据时有了很大的优势。
     
    和NSExpression一样,NSPredicate一直在提醒我们Foundation有多么好:它不仅仅十分有用,它精致的构架和设计也是我们写代码时灵感的来源。
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/feng-a/p/4218747.html
Copyright © 2011-2022 走看看