你們在日常的開發過程當中多多少少都會接觸到數據篩選,那勢必會用到NSPredicate
,這個類和我上一篇博文中提到的valueForKeyPath同樣很強大。它的使用主要集中在兩個方法中git
- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate;
- (void)filterUsingPredicate:(NSPredicate *)predicate;
還有NSSet
和NSMutableSet
也能夠用這個類篩選。github
下面我就來一一介紹這個類的用法,相信你們看完後會和我同樣認爲這個類真的很強大。正則表達式
NSArray *array = @[@"jim", @"cook", @"jobs", @"sdevm"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"length > 3"]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
打印數據庫
( cook, jobs, sdevm )
lenght
就是對數組成員執行[xxxx lenght]而後判斷返回的NSUInteger值是否大於3。擴展到NSString其餘方法好比integerValue
數組
NSArray *array = @[@"2", @"3", @"4", @"5"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"integerValue >= %@", @3]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
若是我不想用任何實例方法,想篩選成員自己應該怎麼作呢。這時候就能夠用self
來代替網站
NSPredicate *pre = [NSPredicate predicateWithFormat:@"self CONTAINS %@", @3];
CONTAINS
用法後面會講到atom
再擴展到模型lua
Test.hcode
@interface Test : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSNumber *code; @end
Test *test1 = [[Test alloc]init]; test1.name = @"西湖"; test1.code = @1; Test *test2 = [[Test alloc]init]; test2.name = @"西溪溼地"; test2.code = @2; Test *test3 = [[Test alloc]init]; test3.name = @"靈隱寺"; test3.code = @3; NSArray *array = @[test1, test2, test3]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"code >= %@", @2]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
篩選出數組成員[test code]
方法(code屬性的get方法)返回值>=2的成員。這裏的比較運算符一樣也可使用==
、!=
、<=
、<
。orm
其實==
不只能夠用來比較NSNumber對象,還能夠用來判斷NSString對象是否相同。
NSPredicate *pre = [NSPredicate predicateWithFormat:@"name == %@", @"西湖"];
篩選出name
是"西湖"的對象數組。
==
比較運算符能夠起到- (BOOL)isEqualToString:(NSString *)aString;
方法的效果,來判斷字符串是否相同。那麼字符串中包含某個字符串應該如何判斷呢,在NSPredicate中能夠用CONTAINS
(大小寫均可以)來表示包含關係。NSPredicate *pre = [NSPredicate predicateWithFormat:@"name CONTAINS %@", @"湖"];
當判斷的時候須要忽略大小寫可使用[cd]
[c] 忽略大小寫
使用:
NSPredicate *pre = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", @"abc"];
再涉及到一些更復雜的查詢語句,好比判斷字符串以某個字符串開頭或者結尾,通配符的使用。
BEGINSWITH(已某個字符串開頭, begins with)
NSString *targetString = @"h"; NSPredicate *pre = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@",targetString];
ENDSWITH(已某個字符串結尾, ends with)
NSString *targetString = @"ing"; NSPredicate *pre = [NSPredicate predicateWithFormat:@"name ENDSWITH %@",targetString];
通配符 LIKE
*表明一個或者多個或者是空
Test *test1 = [[Test alloc]init]; test1.name = @"absr"; test1.code = @1; Test *test2 = [[Test alloc]init]; test2.name = @"asb"; test2.code = @2; Test *test3 = [[Test alloc]init]; test3.name = @"raskj"; test3.code = @3; NSArray *array = @[test1, test2, test3]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"name LIKE %@", @"?b*"]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
結果是隻有test1符合,like
也能夠接受[cd]
NSPredicate *pre = [NSPredicate predicateWithFormat:@"name LIKE[cd] %@", @"?b*"];
IN
、BETWEEN
、AND
、OR
、NOT
IN(之中)
NSPredicate *pre = [NSPredicate predicateWithFormat:@"code IN %@", @[@1, @3]];
判斷code是否@1或者是@2,也就是是否在數組中。
OR(或,能夠用||代替)
OR
能夠用來代替IN
達到一樣的效果,可是OR
更靈活。
NSPredicate *pre = [NSPredicate predicateWithFormat:@"code == %@ OR code == %@ ", @1, @3];
效果和IN
同樣,可是OR
能夠判斷不僅一個屬性
NSPredicate *pred = [NSPredicate predicateWithFormat:@"code == %@ OR name == %@ ", @1, @"asb"];
BETWEEN(之間)
一般用於判斷NSNumber對象
NSPredicate *pred = [NSPredicate predicateWithFormat:@"code BETWEEN {1, 3}"];
判斷code是否>=1且<=3
AND(且,能夠用&&代替)
NSPredicate *pred = [NSPredicate predicateWithFormat:@"code >= %@ AND code <=%@", @1, @3];
NOT(非,能夠用!代替)
NOT
最多見的用法就是從一個數組中剔除另一個數組的數據,可能有點繞,舉個例子就很明朗了。
NSArray *arrayFilter = @[@"abc1", @"abc2"]; NSArray *arrayContent = @[@"a1", @"abc1", @"abc4", @"abc2"]; NSPredicate *thePredicate = [NSPredicate predicateWithFormat:@"NOT (SELF in %@)", arrayFilter]; NSLog(@"%@",[arrayContent filteredArrayUsingPredicate:thePredicate]);
打印
( a1, abc4 )
比起循環比較再加到新數組中,簡單的不止一兩點。
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;
方法建立,還有另外一種經常使用的方法:+ (NSPredicate*)predicateWithBlock:(BOOL (^)(id evaluatedObject, NSDictionary *bindings))block
,用Block形式建立NSPredicate *pre = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { Test *test = (Test *)evaluatedObject; if (test.code.integerValue > 2) { return YES; } else{ return NO; } }];
參數evaluatedObject
表示數組成員,block必須返回YES或者NO,分別表示匹配仍是不匹配。請忽略bindings
參數,具體做用我也沒搞清楚。
若是須要匹配數個屬性的篩選,用AND
或者OR
來串聯顯然有點麻煩,NSCompoundPredicate
類能夠知足咱們的需求,它能夠將多個NSPredicate
對象的組合,組合方式能夠是AND
或者OR
。
NSPredicate *pre1 = [NSPredicate predicateWithFormat:@"code >= %@", @3]; NSPredicate *pre2 = [NSPredicate predicateWithFormat:@"code <= %@", @2]; //以AND形式組合 NSPredicate *pre = [NSCompoundPredicate andPredicateWithSubpredicates:@[pre1,pre2]]; //以OR形式組合 NSPredicate *pre = [NSCompoundPredicate orPredicateWithSubpredicates:@[pre1, pre2]];
- (BOOL)evaluateWithObject:(id)object;
,用法:Test *test1 = [[Test alloc]init]; test1.name = @"absr"; test1.code = @1; NSPredicate *pres = [NSPredicate predicateWithFormat:@"code == %@", @2]; BOOL match = [pres evaluateWithObject:test1];
固然最經常使用的仍是配合配合正則表達式,列舉幾個經常使用的正則
是否以a開頭以e結尾
NSString *string=@"assdbfe"; NSString *targetString=@"^a.+e$"; NSPredicate *pres = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", targetString]; BOOL match = [pres evaluateWithObject:string];
是不是郵箱
NSString *strRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{1,5}";
是不是手機號
NSString *strRegex = @"[0-9]{1,20}";
不得不說,在利用+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;
方法建立的NSPredicate對象的時候有個坑。
在某些狀況下,相似於上面例子中的code
字符串不是很明確,建立的時候就會這樣使用
Test *test1 = [[Test alloc]init]; test1.name = @"absr"; test1.code = @1; Test *test2 = [[Test alloc]init]; test2.name = @"asb"; test2.code = @2; Test *test3 = [[Test alloc]init]; test3.name = @"raskj"; test3.code = @3; NSArray *array = @[test1, test2, test3]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"%@ == %@", @"code", @2]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
注意NSPredicate對象的初始化方式。運行這塊代碼你會發現test2對象沒有被查詢出來。打印pre
發現"code" == 2
,這說明查找的是"code"
方法的返回值,這顯然行不通。
NSPredicate *pre = [NSPredicate predicateWithFormat:@"%K == %@", @"code", @2];
就不會被坑
%K
的K
必須是大寫。NSPredicate幾乎能夠知足全部形式的查詢,配合Core Data的數據庫查詢固然不在話下。NSPredicate用法不僅這些,有興趣的同窗能夠看下nshipster網站的這篇博文,裏面提到了一些我沒有涉及到的用法。