天天看點

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,如需轉載請自行聯系原作者