NSPredicate
一、简介
NSPredicate
指定数据被获取或者过滤的方式,是一个Foundation类。
Cocoa框架中的NSPredicate用于指定过滤器的条件(即查询),它的原理和用法都像SQL的WHERE
和正则表达式一样,作用相当于数据库的过滤器。
最常用到的函数:+ predicateWithFormat: 创建谓词串
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Herbie'"];//注意:如果谓词串中的文本块未被引用,则被看做是键路径,即需要用引号表明是字符串,单引号,双引号均可.键路径可以在后台包含许多强大的功能
二、谓词语法
范例数据源:
索引 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
名 | Alice | Bob | Charlie | Quentin |
姓 | Smith | Jones | Smith | Alberts |
年龄 | 24 | 27 | 33 | 31 |
背景:
@interface Person : NSObject @property NSString *firstName; @property NSString *lastName; @property NSNumber *age; @endNSArray *firstNames = @[ @"Alice", @"Bob", @"Charlie", @"Quentin" ]; NSArray *lastNames = @[ @"Smith", @"Jones", @"Smith", @"Alberts" ]; NSArray *ages = @[ @24, @27, @33, @31 ];NSMutableArray *people = [NSMutableArray array]; [firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {Person *person = [[Person alloc] init];person.firstName = firstNames[idx];person.lastName = lastNames[idx];person.age = ages[idx];[people addObject:person]; }];NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"firstName = 'Bob'"]; NSPredicate *smithPredicate = [NSPredicate predicateWithFormat:@"lastName = %@", @"Smith"]; NSPredicate *thirtiesPredicate = [NSPredicate predicateWithFormat:@"age >= 30"];// ["Bob Jones"] NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:bobPredicate]);// ["Alice Smith", "Charlie Smith"] NSLog(@"Smiths: %@", [people filteredArrayUsingPredicate:smithPredicate]);// ["Charlie Smith", "Quentin Alberts"] NSLog(@"30's: %@", [people filteredArrayUsingPredicate:thirtiesPredicate]);
1.替换:
为了简便,多数不使用替换,而是直接输入 key path 、对象 和 $VARIABLE_NAME 。
%@
是对值为字符串,数字或者日期的对象的替换值。%K
是key path的替换值。$VARIABLE_NAME
是可以被NSPredicate -predicateWithSubstitutionVariables:
替换的值。
NSPredicate *ageIs33Predicate = [NSPredicate predicateWithFormat:@"%K = %@", @"age", @33]; //为了简便,也写作:@"age = 33" NSLog(@"Age 33: %@", [people filteredArrayUsingPredicate:ageIs33Predicate]); //运行结果: ["Charlie Smith"] NSPredicate *namesBeginningWithLetterPredicate = [NSPredicate predicateWithFormat:@"(firstName BEGINSWITH[cd] $letter) OR (lastName BEGINSWITH[cd] $letter)"]; //为了简便,也写作:@"(firstName BEGINSWITH[cd] 'A') OR (lastName BEGINSWITH[cd] 'A')" NSLog(@"'A' Names: %@", [people filteredArrayUsingPredicate:[namesBeginningWithLetterPredicate predicateWithSubstitutionVariables:@{@"letter": @"A"}]]); // 运行结果:["Alice Smith", "Quentin Alberts"]
2.基本比较:比较运算符
=
,==
:左右相等。>=
,=>
:大于或者等于。<=
,=<
:小于等于。>
<
!=
,<>
:不等于。BETWEEN
:左边的表达式等于右边的表达式的值或者介于它们之间。右边是一个有两个指定上限和下限的数值的数列(指定顺序的数列)。
比如,
1 BETWEEN { 0 , 33 }
,或者$INPUT BETWEEN { $LOWER, $UPPER }
。
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"number BETWEEN {1,5}"];
3.字符串比较
字符串比较在默认的情况下是区分大小写和音调的。在方括号中用关键字符c和d来修改操作,比如firstname BEGINSWITH[cd] $FIRST_NAME。
[c]不区分大小写 , [d]不区分发音符号即没有重音符号 , [cd]既不区分大小写,也不区分发音符号。
BEGINSWITH
:左边的表达式以右边的表达式作为开始。CONTAINS
:左边的表达式包含右边的表达式。ENDSWITH
:左边的表达式以右边的表达式作为结束。LIKE
:左边的表达式等于右边的表达式:?
和*
可作为通配符,其中?
匹配1个字符,*
匹配0个或者多个字符。MATCHES
:正则表达式:左边的表达式根据ICU v3(更多内容请查看ICU User Guide for Regular Expressions)的regex风格比较,等于右边的表达式。SELF :字符串本身,例:@"SELF == 'APPLE'"
//name 均是对象的属性 [NSPredicate predicateWithFormat:@"name CONTAINS[cd] 'xxx'"]; //包含某个(xxx)字符串 [NSPredicate predicateWithFormat:@"name BEGINSWITH[c] 'xxx'"]; //以某个字符串开头 [NSPredicate predicateWithFormat:@"name ENDSWITH[d] 'xxx'"]; //以某个字符串结束 [NSPredicate predicateWithFormat:@"name LIKE[cd] '*er*'"]; //*代表通配符,Like也接受[cd]. [NSPredicate predicateWithFormat:@"name LIKE[cd] '???er*'"]; NSString *regex = @"^A.+e$"; //以A开头,e结尾 [NSPredicate predicateWithFormat: @"name MATCHES %@",regex]; //在数组筛选中,如果我不想用任何实例方法,想筛选成员本身时,可以用self来代替 NSArray *array = @[@"jim", @"cook", @"jobs", @"APPLE"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF == 'APPLE'"]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
4.基本复合谓词
AND
,&&
:逻辑与
.OR
,||
:逻辑或
.NOT
,!
:逻辑非
.
5.合计操作
5.1关系操作
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' }
。
5.2数组操作
array[index]
:指定数组
中特定索引处的元素。array[FIRST]
:指定数组
中的第一个元素。array[LAST]
:指定数组
中的最后一个元素。array[SIZE]
:指定数组
的大小。
5.3布尔值谓词
TRUEPREDICATE
:结果始终为真
的谓词。FALSEPREDICATE
:结果始终为假
的谓词。
三、应用场景
1.集合中使用NSPredicate
Foundation提供使用谓词(predicate)来过滤NSArray
/NSMutableArray
&NSSet
/NSMutableSet
的方法。
对不可变的集合(NSArray
&NSSet)
,通过评估接收到的predicate,用 `filteredArrayUsingPredicate:` 或
`filteredSetUsingPredicate:` 方法来返回一个不可变集合:
filteredArrayUsingPredicate: 是NSArray数组的一种类别方法,循环过滤数组中的内容,将值为YES的对象累积到结果数组中返回。
//对NSArray进行过滤 NSArray *array = [[NSArray alloc]initWithObjects:@"beijing",@"shanghai",@"guangzou",@"wuhan", nil]; NSString *string = @"ang"; NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@",string]; NSLog(@"%@",[array filteredArrayUsingPredicate:pred]);
对可变集合(NSMutableArray
&NSMutableSet
),可以使用方法filterUsingPredicate:
,它可以通过运行接收到的谓词来移除评估结果为FALSE
的对象。
NSDictionary
可以用谓词来过滤它的键和值(两者都为NSArray
对象)。NSOrderedSet
可以由过滤的NSArray
或NSSet
生成一个新的有序的集,或者NSMutableSet
可以简单的removeObjectsInArray:
,来传递通过_否定_predicate过滤的对象。
注意在筛选过程中,要灵活利用成员实例方法,如:
lenght、
integerValue
NSArray *array = @[@"jim", @"cook", @"jobs", @"sdevm"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"length > 3"];//lenght就是对数组成员执行[xxxx lenght]然后判断返回的NSUInteger值是否大于3 NSLog(@"%@", [array filteredArrayUsingPredicate:pre]); //结果:( cook, jobs, sdevm )//扩展到NSString其他方法又比如integerValue: NSArray *array = @[@"2", @"3", @"4", @"5"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"integerValue >= %@", @3]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
如果我不想用任何实例方法,想筛选成员本身应该怎么做呢?这时候就可以用
self
来代替:
NSArray *array = @[@"2", @"3", @"4", @"5"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"self CONTAINS %@", @3]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]);
2.模型中使用NSPredicate
--- 由集合拓展到模型
由`利用成员实例方法(集合中成员的方法)`拓展到`利用成员方法(集合中对象的属性的方法)`
筛选出数组成员方法[people firstName](firstName
属性的get方法)返回值 = 'Bob' 的成员。
NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"firstName = 'Bob'"];// ["Bob Jones"] NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:bobPredicate]);
3.多重筛选NSCompoundPredicate
如果需要匹配数个属性的筛选,用AND
或者OR
来串联显然有点麻烦。
NSCompoundPredicate
类可以满足我们的需求,它可以将多个NSPredicate
对象的组合,组合方式可以是AND
或者OR
andPredicateWithSubpredicates: orPredicateWithSubpredicates:
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]];
4.匹配用法evaluateWithObject:
其实NSPredicate不仅可以用于筛选,还可以用来判断匹配直接返回是否符合。
主要方法是 -(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}";
5.Core Data中使用NSPredicate
NSFetchRequest
有一个predicate
属性,它可以指定管理对象应该被获取的逻辑条件。谓词的使用规则在这里同样适用,唯一的区别在于,在管理对象环境中,谓词由持久化存储助理(persistent store coordinator)评估,而不像集合那样在内存中被过滤。
//查询NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];//条件查询NSPredicate *predicate = [NSPredicate predicateWithFormat:@""];request.predicate = predicate;//执行查询NSArray *objectArray = [self.managedObjectContext executeFetchRequest:request error:nil];if (![objectArray count]) {NSLog(@"未找到符合条件的对象!");}return objectArray;
四、Block谓词 --- 另一种创建NSPredicate的方式
最后,如果你实在不愿意学习NSPredicate
的格式语法,你也可以学学NSPredicate +predicateWithBlock:
。
NSPredicate *shortNamePredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {return [[evaluatedObject firstName] length] <= 5;}];// ["Alice Smith", "Bob Jones"] NSLog(@"Short Names: %@", [people filteredArrayUsingPredicate:shortNamePredicate]);
...好吧,虽然使用predicateWithBlock:
是懒人的做法,但它也并不是一无是处。
事实上,因为block可以封装任意的计算,所以有一个查询类是无法以NSPredicate
格式字符串形式来表达的(比如对运行时被动态计算的值的评估)。而且当同一件事情可以用NSExpression
结合自定义选择器来完成时,block为完成工作提供了一个方便的接口。
重要提示:由predicateWithBlock:
生成的NSPredicate
不能用于由SQLite
存储库支持的Core Data数据的提取要求。
本文参考自NSHipster.cn、bawn。
转载于:https://www.cnblogs.com/chenyuansheng/p/5319737.html
NSPredicate相关推荐
- NSPredicate的使用
NSpredicate介绍 首先,我们需要知道什么是谓词,让我们看看官方的解释: The NSPredicate class is used to define logical conditions ...
- HTTPPost/AFNetWorking/JSONModel/NSPredicate
一.HTTPPost================================================ 1. POST方式发送请求 HTTP协议下默认数据发送请求方法是GET方式,若需要 ...
- IOS NSPredicate 查询、搜索
简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取. 最常用到的函数 + (NSPredicate *)predicateWith ...
- NSPredicate 查询/搜索
IOS NSPredicate 查询.搜索 简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取. 最常用到的函数 + (NSPre ...
- 好用的NSPredicate
NSPredicate的用法 一般来说这种情况还是蛮多的,比如你从文件中读入了一个array1,然后想把程序中的一个array2中符合array1中内容的元素过滤出来. 正 常傻瓜一点就是两个for循 ...
- NSPredicate的用法
一般来说这种情况还是蛮多的,比如你从文件中读入了一个array1,然后想把程序中的一个array2中符合array1中内容的元素过滤出来. 正 常傻瓜一点就是两个for循环,一个一个进行比较,这样效率 ...
- IOS自带正则表达式NSPredicate的使用
首先举一个例子: 匹配9-15个由字母/数字组成的字符串的正则表达式: NSString * regex = @"^[A-Za-z0-9]{9,15}$"; NSP ...
- iOS之深入解析谓词NSPredicate的语法与应用
一.简介 NSPredicate 的官方解释如下: The NSPredicate class is used to define logical conditions used to constra ...
- 谓词NSPredicate的使用
谓词是用来为数据添加过滤条件,从而更加精确的找到找到所描述条件的数据.苹果为我们封装好了NSPredicate类,我们可以很方便的得到我们需要的过滤条件. 谓词的简单语法总结: 比较运算: > ...
最新文章
- MySQL高可用群集------配置MMM高可用架构
- Idea(二) 解决IDEA卡顿问题及相关基本配置(转)
- 《ES6标准入门》49~68Page 数值的拓展 数组的拓展
- django mysql内存泄漏_Django的:使内存的关系,而不保存到数据库
- 初学者:如何使用虚拟PC将Windows 7安装到虚拟机
- 初一模拟赛总结(4.7)
- 暗黑破坏神(ssl 2295)
- 5000并发的qps是多少_高并发架构设计
- csdn飞鸽传书 打了七天七夜
- 甘特图制作_使用excel制作甘特图其实很简单,仅需4步搞定,项目进度一目了然...
- Python import其他文件夹的文件
- 图像处理-与,或等运算
- 开源OA协同办公平台搭建教程丨模糊人员匹配功能配置说明
- 谷歌金山词霸/搜狗、QQ、google输入法模式分析及展望
- 固态硬盘能不能提高计算机速度,固态硬盘掉速如何解决?几招轻松提升SSD速度方法 (全文)...
- windows10桌面图标异常,显示为白色图标
- YunEngine SDK已经开始发放了!!!
- 小程序 function(res)与(res) =的区别
- 相当不错的在线用户故事地图绘制工具
- 安装pip最新版 20.1