天天看点

iOS开发-NSPredicate

Cocoa中谓词(Predicate)提供了一个通用的查询方式处理数据,可以获取和指定数据的过滤形式,Cocoa实际开发中可以是使用NSPredicate及其父类NSComparisonPredicate和NSCompoundPredicate.其风格类似于SQL查询语言和正则表达式的混合体,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。一般来说稍微操作过数据库基本上很容易理解其中的方法,至于使用的方法也很简单。

Foundation提供使用谓词(predicate)来过滤NSArray/NSMutableArray&NSSet/NSMutableSet的方法。

不可变的集合,NSArray&NSSet,可以通过评估接收到的predicate来返回一个不可变集合的方法filteredArrayUsingPredicate和filteredSetUsingPredicate;

可变集合,NSMutableArray&NSMutableSet,可以使用方法filterUsingPredicate:可以通过运行接收到的谓词来移除评估结果为FALSE的对象。

首先来一段比较简单的代码: 

1

2

3

4

<code>NSPredicate</code> <code>*predicate = [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"SELF IN %@"</code><code>, @[@</code><code>"keso"</code><code>, @</code><code>"FlyElephant"</code><code>, @</code><code>"博客园"</code><code>]];</code>

<code>if</code> <code>([predicate evaluateWithObject:@</code><code>"keso"</code><code>]) {</code>

<code>    </code><code>NSLog</code><code>(@</code><code>"keso"</code><code>);</code>

<code>};</code>

 第一行代码初始化一个查询条件,第二句就是判断数据在不在结果集中,跟SQL基本上一样,通过IN就能大概了解其功能,SELF表示本身,非常常用。

接下来可以类似于SQL中like语句的代码:

5

6

<code>NSArray</code> <code>*array = [[</code><code>NSArray</code> <code>alloc]initWithObjects:@</code><code>"北京"</code><code>,@</code><code>"上海"</code><code>,@</code><code>"广州"</code><code>,@</code><code>"深圳"</code><code>,</code><code>nil</code><code>];</code>

<code> </code><code>NSPredicate</code> <code>*preBegin= [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"SELF beginswith[c] %@"</code><code>,@</code><code>"北"</code><code>];</code>

<code> </code><code>NSPredicate</code> <code>*preContain= [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"SELF contains[c] %@"</code><code>,@</code><code>"海"</code><code>];</code>

<code> </code> 

<code> </code><code>NSLog</code><code>(@</code><code>"%@"</code><code>,[array filteredArrayUsingPredicate:preBegin][0]);</code>

<code> </code><code>NSLog</code><code>(@</code><code>"%@"</code><code>,[array filteredArrayUsingPredicate:preContain][0]);</code>

 第一次就是先初始化数组,然后创建条件,通过filteredArrayUsingPredicate过滤数组;

NSDictionary可以用谓词来过滤它的键和值(两者都为NSArray对象);

NSOrderedSet可以由过滤的NSArray或NSSet生成一个新的有序的集,或者NSMutableSet可以简单的removeObjectsInArray来传递通过否定predicate过滤的对象。

谓词的在Core Data同样适用,在管理对象环境中,谓词由持久化存储助理(persistent store coordinator)评估,而集合则是内存中过滤。这时候我们有必要里了解一下基本比较运算符:

=, ==:左边的表达式和右边的表达式相等。

&gt;=, =&gt;:左边的表达式大于或者等于右边的表达式。

&lt;=, =&lt;:左边的表达式小于等于右边的表达式。

&gt;:左边的表达式大于右边的表达式。

&lt;:左边的表达式小于右边的表达式。

!=, &lt;&gt;:左边的表达式不等于右边的表达式。

BETWEEN:左边的表达式等于右边的表达式的值或者介于它们之间。右边是一个有两个指定上限和下限的数值的数列(指定顺序的数列)。比如,1 BETWEEN { 0 , 33 },或者INPUT BETWEEN {INPUT BETWEEN {LOWER, $UPPER }。可参考以下代码:

7

8

9

<code>NSPredicate</code> <code>*betweenPredicate =</code>

<code>   </code><code>[</code><code>NSPredicate</code> <code>predicateWithFormat: @</code><code>"attributeName BETWEEN %@"</code><code>, @[</code><code>@1</code><code>, </code><code>@10</code><code>]];</code>

<code>   </code> 

<code>   </code><code>NSDictionary</code> <code>*dictionary = @{ @</code><code>"attributeName"</code> <code>: </code><code>@5</code> <code>};</code>

<code>   </code><code>BOOL</code> <code>between = [betweenPredicate evaluateWithObject:dictionary];</code>

<code>   </code><code>if</code> <code>(between) {</code>

<code>       </code><code>NSLog</code><code>(@</code><code>"比较运算符between"</code><code>);</code>

<code>   </code><code>} </code>

基本复合谓词

AND, &amp;&amp;:逻辑与.

OR, ||:逻辑或.

NOT, !:逻辑非

字符串比较

字符串比较非常常用,以下的都应该比较熟悉:

BEGINSWITH[cd] $FIRST_NAME。

BEGINSWITH:左边的表达式以右边的表达式作为开始。

CONTAINS:左边的表达式包含右边的表达式。

ENDSWITH:左边的表达式以右边的表达式作为结束。

LIKE:左边的表达式等于右边的表达式:?和*可作为通配符,其中?匹配1个字符,*匹配0个或者多个字符。

MATCHES:左边的表达式根据ICU v3的regex风格比较,等于右边的表达式。

可参考以下代码:

<code>NSString</code> <code>*regex = @</code><code>"[A-Za-z]+"</code><code>;</code>

<code>NSPredicate</code> <code>*matchpredicate = [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"SELF MATCHES %@"</code><code>, regex];</code>

<code>if</code> <code>([matchpredicate evaluateWithObject:@</code><code>"keso"</code><code>]) {</code>

<code>    </code><code>NSLog</code><code>(@</code><code>"匹配成功"</code><code>);</code>

<code>}</code>

关系操作

ANY,SOME:指定下列表达式中的任意元素。比如,ANY children.age &lt; 18。

ALL:指定下列表达式中的所有元素。比如,ALL children.age &lt; 18。

NONE:指定下列表达式中没有的元素。比如,NONE children.age &lt; 18。它在逻辑上等于NOT (ANY ...)。

IN:等于SQL的IN操作,左边的表达必须出现在右边指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' }。

数组操作

array[index]:指定数组中特定索引处的元素。

array[FIRST]:指定数组中的第一个元素。

array[LAST]:指定数组中的最后一个元素。

array[SIZE]:指定数组的大小。

布尔值谓词

TRUEPREDICATE:结果始终为真的谓词。

FALSEPREDICATE:结果始终为假的谓词。

下面提供一个简单使用谓词搜索类对象的代码:

新建一个People类,头文件:

10

11

<code>@interface</code> <code>People : </code><code>NSObject</code>

<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSString</code> <code>*FirstName;</code>

<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSString</code> <code>*LastName;</code>

<code>@property</code> <code>(</code><code>nonatomic</code><code>) </code><code>NSInteger</code> <code>Height;</code>

<code>- (</code><code>NSString</code> <code>*)description;</code>

<code>@end</code>

 People.m文件:

<code>@implementation</code> <code>People</code>

<code>- (</code><code>NSString</code> <code>*)description {</code>

<code>   </code><code>return</code>  <code>[</code><code>NSString</code> <code>stringWithFormat:@</code><code>"%@%@"</code><code>,</code><code>self</code><code>.LastName, </code><code>self</code><code>.FirstName];</code>

 具体实现代码:

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<code>NSArray</code> <code>*firstNames =[[</code><code>NSArray</code> <code>alloc]initWithObjects:@</code><code>"泽东"</code><code>, @</code><code>"恩来"</code><code>, @</code><code>"介石"</code><code>, @</code><code>"中山"</code><code>, </code><code>nil</code><code>];</code>

<code>NSArray</code> <code>*lastNames = @[ @</code><code>"毛"</code><code>, @</code><code>"周"</code><code>, @</code><code>"蒋"</code><code>, @</code><code>"孙"</code> <code>];</code>

<code>NSArray</code> <code>*familiar = @[ </code><code>@100</code><code>, </code><code>@99</code><code>, </code><code>@99</code><code>, </code><code>@98</code> <code>];</code>

<code>NSMutableArray</code> <code>*dataList= [</code><code>NSMutableArray</code> <code>array];</code>

<code>[firstNames enumerateObjectsUsingBlock:^(</code><code>id</code> <code>obj, </code><code>NSUInteger</code> <code>idx, </code><code>BOOL</code> <code>*stop) {</code>

<code>    </code><code>People *people= [[People alloc] init];</code>

<code>    </code><code>people.FirstName = firstNames[idx];</code>

<code>    </code><code>people.LastName = lastNames[idx];</code>

<code>    </code> 

<code>    </code><code>people.Height= [familiar[idx] integerValue];</code>

<code>    </code><code>[dataList addObject:people];</code>

<code>}];</code>

<code>NSPredicate</code> <code>*firstPredicate = [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"FirstName = '恩来'"</code><code>];</code>

<code>NSPredicate</code> <code>*lastPredicate = [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"LastName = %@"</code><code>, @</code><code>"蒋"</code><code>];</code>

<code>NSPredicate</code> <code>*heightPredicate = [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"Height &lt; 99"</code><code>];</code>

<code>//名搜索</code>

<code>NSLog</code><code>(@</code><code>"名: %@"</code><code>,[dataList filteredArrayUsingPredicate:firstPredicate][0]);</code>

<code>//姓搜索</code>

<code>NSLog</code><code>(@</code><code>"姓: %@"</code><code>, [dataList filteredArrayUsingPredicate:lastPredicate][0]);</code>

<code>//知名度</code>

<code>NSLog</code><code>(@</code><code>"知名度: %@"</code><code>, [dataList filteredArrayUsingPredicate:heightPredicate][0]);</code>

其实开始讲的<code>NSCompoundPredicate和</code><code>NSComparisonPredicate,因为有关系操作,基本上类似,如果通过混合搜索可以使用and,or实现,比如一下代码是等价的:</code>

<code>NSCompoundPredicate</code> <code>*comPredicate=[</code><code>NSCompoundPredicate</code> <code>andPredicateWithSubpredicates:@[[</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"Height &gt; 90"</code><code>], [</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"FirstName = %@"</code><code>, @</code><code>"介石"</code><code>]]];</code>

<code>NSPredicate</code> <code>*secondPredicate=[</code><code>NSPredicate</code> <code>predicateWithFormat:@</code><code>"(Height &gt; 90) AND (FirstName = %@)"</code><code>, @</code><code>"介石"</code><code>];</code>

  NSComparisonPredicate有两个调用的静态方法:

<code>+ (</code><code>NSComparisonPredicate</code> <code>*)predicateWithLeftExpression:(</code><code>NSExpression</code> <code>*)lhs rightExpression:(</code><code>NSExpression</code> <code>*)rhs modifier:(</code><code>NSComparisonPredicateModifier</code><code>)modifier type:(</code><code>NSPredicateOperatorType</code><code>)type options:(</code><code>NSComparisonPredicateOptions</code><code>)options;</code>

<code>+ (</code><code>NSComparisonPredicate</code> <code>*)predicateWithLeftExpression:(</code><code>NSExpression</code> <code>*)lhs rightExpression:(</code><code>NSExpression</code> <code>*)rhs customSelector:(</code><code>SEL</code><code>)selector;</code>

  其实就是一个表达式的拼接的过程,不过具体的实现苹果给封装好了,一下是NSPredicateOperatorType类型:

<code>typedef</code> <code>NS_ENUM</code><code>(</code><code>NSUInteger</code><code>, </code><code>NSPredicateOperatorType</code><code>) {</code>

<code>    </code><code>NSLessThanPredicateOperatorType</code> <code>= 0, </code><code>// compare: returns NSOrderedAscending</code>

<code>    </code><code>NSLessThanOrEqualToPredicateOperatorType</code><code>, </code><code>// compare: returns NSOrderedAscending || NSOrderedSame</code>

<code>    </code><code>NSGreaterThanPredicateOperatorType</code><code>, </code><code>// compare: returns NSOrderedDescending</code>

<code>    </code><code>NSGreaterThanOrEqualToPredicateOperatorType</code><code>, </code><code>// compare: returns NSOrderedDescending || NSOrderedSame</code>

<code>    </code><code>NSEqualToPredicateOperatorType</code><code>, </code><code>// isEqual: returns true</code>

<code>    </code><code>NSNotEqualToPredicateOperatorType</code><code>, </code><code>// isEqual: returns false</code>

<code>    </code><code>NSMatchesPredicateOperatorType</code><code>,</code>

<code>    </code><code>NSLikePredicateOperatorType</code><code>,</code>

<code>    </code><code>NSBeginsWithPredicateOperatorType</code><code>,</code>

<code>    </code><code>NSEndsWithPredicateOperatorType</code><code>,</code>

<code>    </code><code>NSInPredicateOperatorType</code><code>, </code><code>// rhs contains lhs returns true</code>

<code>    </code><code>NSCustomSelectorPredicateOperatorType</code><code>,</code>

<code>    </code><code>NSContainsPredicateOperatorType</code> <code>NS_ENUM_AVAILABLE</code><code>(10_5, 3_0) = 99, </code><code>// lhs contains rhs returns true</code>

<code>    </code><code>NSBetweenPredicateOperatorType</code> <code>NS_ENUM_AVAILABLE</code><code>(10_5, 3_0)</code>

本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4264869.html,如需转载请自行联系原作者