你们在日常的开发过程当中多多少少都会接触到数据筛选,那势必会用到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网站的这篇博文,里面提到了一些我没有涉及到的用法。