关于NSPredicate的使用,网上已经有很多文章,有一些很不错,之前看的就是这篇:点击打开链接。根据自己的使用总结下:
我主要是用在对数组的筛选上,相对循环数组然后自己去匹配,要简洁得多。而且对于数组里面嵌套字典或对象的结构很好。
1、NSPredicate的构建:
NSPredicate * filterPredicate = [NSPredicatepredicateWithFormat:@"label.text == '3' "];
使用一段字符串构建,是一段匹配性质的字符串,类似sql的用法。我的理解是,这段字符串可以分为3个部分,左边是用来匹配的东西,右边是被匹配的目标值,中间用来指定用什么关系来匹配。所以也按着这个思路来说NSPredicate的构建。
(1)用来匹配的东西:
SELF 关键词可以用来指定自身,除此之外就是变成自身的属性进行匹配。
- (void)demo_method{ NSArray * arr = @[@{@"num":@1},@{@"num": @2},@{@"num": @3},@{@"num": @4}]; NSPredicate * arrPredicate = [NSPredicate predicateWithFormat:@"num = 3"]; NSArray * filteredArr = [arr filteredArrayUsingPredicate:arrPredicate]; NSLog(@"%@",filteredArr); }这里使用@“num = 3”;会将num当做键获取值,然后用这个值来进行匹配。因为对象的属性页可以通过ValueForKey获得,所以如果这里的数组里面是放了一个个的对象,而这个对象有一个属性num,依然可以使用这个 NSPredicate进行筛选。而且当数据嵌套很深时依然可以使用:
- (void)instancePredicate2{ NSMutableArray * testArr = [[NSMutableArray alloc]initWithCapacity:4]; for (int i = 0; i<15; i++) { UILabel * label = [[UILabel alloc]init]; label.text = [NSString stringWithFormat:@"%d",i]; testObject * obj = [[testObject alloc]init]; obj.label = label; [testArr addObject:obj]; } NSLog(@"%@",testArr); NSPredicate * filterPredicate = [NSPredicate predicateWithFormat:@"label.text.length == 2"]; NSArray * filteredArr = [testArr filteredArrayUsingPredicate:filterPredicate]; NSLog(@"%@",((testObject *)filteredArr[0]).label); }testObject是自定义的一个类,只有一个UILabel * label的属性,数组里面添加的是 testObject对象,使用字符串为“label.text.length”可以一层层的向下获取属性,然后进行匹配,主要是这里可以使用.(点)这个字符,非常好。
(2)进行匹配的关系以及对应的被匹配的目标值的写法:
借鉴网上其他文章,有这些运算符:比较运算符>,<,==,>=,<=,!= ,IN,BETWEEN,BEGINSWITH、ENDSWITH、CONTAINS,LIKE,MATCHES
比较运算符没什么可多说的,
IN:
NSArray * arr = @[@214411,@12,@553,@34,@6335];
NSPredicate * pre = [NSPredicate predicateWithFormat:@"SELF IN %@",arr]; flag = [pre evaluateWithObject:@214411]; //flag结果为YES
IN用于匹配在一个数组中是否存在特定的值或对象。也可以这样写:
NSPredicate * pre = [NSPredicate predicateWithFormat:@"SELF IN {214411,12,553,34,6335}"]; flag = [pre evaluateWithObject:@214411];或者使用类似stringWithFormater:的写法,在引号里面使用%@,外面跟上相应的对象,这样可以匹配任意类的对象:
NSPredicate * pre = [NSPredicate predicateWithFormat:@"SELF IN {%@,6335}",@214411];BETWEEN:
和IN:可以用于数字、日期和字符串,用于判断指定的对象的值是否在给定的两者之间:
NSDateFormatter * formatter = [[NSDateFormatter alloc]init]; [formatter setDateFormat:@"yyyy-MM-dd"]; NSDate * date1 = [formatter dateFromString:@"2014-03-01"]; NSDate * date2 = [formatter dateFromString:@"2014-05-01"]; NSArray * arr = @[date1,date2]; NSPredicate * pre = [NSPredicate predicateWithFormat:@"SELF BETWEEN %@",arr]; flag = [pre evaluateWithObject:[formatter dateFromString:@"2014-4-22"]];被匹配的目标值需要一个数组,而且是只有两个值的数组,都是数字或都是NSDate对象、或字符串。数字就是这两个数提供一个范围,比如3到10,日期也一样,不过字符串不清楚怎么用的。这例子里的日期需要自己构建,如果是在某个项目中已经有了日期和范围,那么两句话就可以判断指定日期是否在特定的范围内,还是很简洁的。
BEGINSWITH、ENDSWITH、CONTAINS:
这3个关键词分别匹配字符串是否已特定的字符串开头、结尾和包含特定字符串;如:@"name CONTAIN[cd] 'ang'";
[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。
LIKE:
LIKE用来匹配字符串,相对上面3个更灵活一些,如:@"name LIKE[cd] '???er*'";
?匹配单个字符,有几个?代表这个位置有几个字符,需要数量匹配上才可以,*匹配多个字符,只要这个位置有字符就可以。使用‘er*’就可以替代BEGINSWITH。
MATCHES:
这个关键词是用来匹配正则表达式的。
以上说的都是一个条件,可以使用AND合并两个条件。
2、NSPredicate的使用:
(1)用于过滤数组:NSPredicate构建之后,数组使用
NSArray * filteredArr = [testArr filteredArrayUsingPredicate:filterPredicate];进行筛选。筛选之后的结果也是一个数组,因为可能会匹配多个值
(2)对某个对象的的属性进行判断:
NSPredicate * pre = [NSPredicate predicateWithFormat:@"SELF BETWEEN %@",arr]; flag = [pre evaluateWithObject:[formatter dateFromString:@"2014-4-22"]];
最后,我认为大于小于、是否包含等判断可以不适用NSPredicate,因为这种判断本身很简单,使用谓词反而麻烦,只有在对数组的每个值都进行判断或者类似日期包含这样较复杂的判断时候,就是用谓词,可以尽量简洁。