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)評估,而集合則是記憶體中過濾。這時候我們有必要裡了解一下基本比較運算符:
=, ==:左邊的表達式和右邊的表達式相等。
>=, =>:左邊的表達式大于或者等于右邊的表達式。
<=, =<:左邊的表達式小于等于右邊的表達式。
>:左邊的表達式大于右邊的表達式。
<:左邊的表達式小于右邊的表達式。
!=, <>:左邊的表達式不等于右邊的表達式。
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, &&:邏輯與.
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 < 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:結果始終為假的謂詞。
下面提供一個簡單使用謂詞搜尋類對象的代碼:
建立一個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 < 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 > 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 > 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,如需轉載請自行聯系原作者