NSpredicate介绍

首先,我们需要知道什么是谓词,让我们看看官方的解释:

The NSPredicate class is used to define logical conditions used to constrain a search either for a fetch or for in-memory filtering.

NSPredicate 类是用来定义逻辑条件约束的获取或内存中的过滤搜索。

可以使用谓词来表示逻辑条件,用于描述对象持久性存储在内存中的对象过滤。

说人话:我是一个过滤器,不符合条件的都滚开。

一、NSPredicate的基本语法

只要我们使用谓词(NSPredicate)都需要为谓词定义谓词表达式,而这个表达式是一个返回BOOL的值。
谓词表达式: 表达式、运算符和值构成。

比较运算符如下

=、==:判断两个表达式是否相等,在谓词中=和==是相同的意思都是判断相等

NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 123"];
if ([predicate evaluateWithObject:testNumber]) {NSLog(@"testString:%@", testNumber);  // testString:123
}

>=,=>:判断左边表达式的值是否大于或等于右边表达式的值
<=,=<:判断右边表达式的值是否小于或等于右边表达式的值
>:判断左边表达式的值是否大于右边表达式的值
<:判断左边表达式的值是否小于右边表达式的值
!=、<>:判断两个表达式是否不相等

BETWEEN:BETWEEN表达式必须满足表达式 BETWEEN {下限,上限}的格式,要求该表达式必须大于或等于下限,并小于或等于上限

NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
if ([predicate evaluateWithObject:testNumber]) {NSLog(@"testString:%@", testNumber);
} else {NSLog(@"不符合条件");
}

逻辑运算符

AND/&&:逻辑与,要求两个表达式的值都为YES时,结果才为YES。

NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
NSLog(@"filterArray:%@", filterArray);

OR/||:逻辑或,要求其中一个表达式为YES时,结果就是YES
NOT/ !:逻辑非,对原有的表达式取反

3.字符串比较运算符

BEGINSWITH:检查某个字符串是否以指定的字符串开头(如判断字符串是否以a开头:BEGINSWITH 'a')
ENDSWITH:检查某个字符串是否以指定的字符串结尾
CONTAINS:检查某个字符串是否包含指定的字符串
LIKE:检查某个字符串是否匹配指定的字符串模板。其之后可以跟?代表一个字符和*代表任意多个字符两个通配符。比如"name LIKE '*ac*'",这表示name的值中包含ac则返回YES;"name LIKE '?ac*'",表示name的第2、3个字符为ac时返回YES。
MATCHES:检查某个字符串是否匹配指定的正则表达式。虽然正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。

注意:字符串比较都是区分大小写和重音符号的。

如:café和cafe是不一样的,Cafe和cafe也是不一样的。如果希望字符串比较运算不区分大小写和重音符号,请在这些运算符后使用[c],[d]选项。其中[c]是不区分大小写,[d]是不区分重音符号,其写在字符串比较运算符之后,

比如:name LIKE[cd] 'cafe',那么不论name是cafe、Cafe还是café上面的表达式都会返回YES。

4.集合运算符

ANY、SOME:集合中任意一个元素满足条件,就返回YES。
ALL:集合中所有元素都满足条件,才返回YES。
NONE:集合中没有任何元素满足条件就返回YES。如:NONE person.age < 18,表示person集合中所有元素的age>=18时,才返回YES。
IN:等价于SQL语句中的IN运算符,只有当左边表达式或值出现在右边的集合中才会返回YES。我们通过一个例子来看一下

NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);

代码的作用是将array中和filterArray中相同的元素去除,输出为:

// 输出
(
a,
abcd
)

array[index]:返回array数组中index索引处的元素
array[FIRST]:返回array数组中第一个元素
array[LAST]:返回array数组中最后一个元素
array[SIZE]:返回array数组中元素的个数

5.直接量

在谓词表达式中可以使用如下直接量

FALSE、NO:代表逻辑假
TRUE、YES:代表逻辑真
NULL、NIL:代表空值
SELF:代表正在被判断的对象自身
"string"或'string':代表字符串
数组:和c中的写法相同,如:{'one', 'two', 'three'}。
数值:包括证书、小数和科学计数法表示的形式
十六进制数:0x开头的数字
八进制:0o开头的数字
二进制:0b开头的数字

6.保留字

下列单词都是保留字(不论大小写)

AND、OR、IN、NOT、ALL、ANY、SOME、NONE、LIKE、CASEINSENSITIVE、CI、MATCHES、CONTAINS、BEGINSWITH、ENDSWITH、BETWEEN、NULL、NIL、SELF、TRUE、YES、FALSE、NO、FIRST、LAST、SIZE、ANYKEY、SUBQUERY、CAST、TRUEPREDICATE、FALSEPREDICATE

注:虽然大小写都可以,但是更推荐使用大写来表示这些保留字

二、谓词的用法

1.定义谓词

一般我们使用下列方法来定义一个谓词

NSPredicate *predicate = [NSPredicate predicateWithFormat:];

下面我们通过几个简单的例子来看看它该如何使用:

定义一个对象,等下我们将在示例中使用

ZLPersonModel.h
#import typedef NS_ENUM(NSInteger, ZLPersonSex) {
ZLPersonSexMale = 0,
ZLPersonSexFamale
};@interface ZLPersonModel : NSObject
/** NSString 姓名 */
@property (nonatomic, copy) NSString *name;
/** NSUInteger 年龄 */
@property (nonatomic, assign) NSUInteger age;
/** ZLPersonSex 性别 */
@property (nonatomic, assign) ZLPersonSex sex;+ (instancetype)personWithName:(NSString *)name age:(NSUInteger)age sex:(ZLPersonSex)sex;@end

例一:对象条件判断

ZLPersonModel *sunnyzl = [ZLPersonModel personWithName:@"sunnyzl" age:29 sex:ZLPersonSexMale];
ZLPersonModel *jack = [ZLPersonModel personWithName:@"jack" age:22 sex:ZLPersonSexMale];
// 首先我们来看一些简单的使用
// 1.判断姓名是否是以s开头的
NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"name LIKE 's*'"];
// 输出为:sunnyzl:1, jack:0
NSLog(@"sunnyzl:%d, jack:%d", [pred1 evaluateWithObject:sunnyzl], [pred1 evaluateWithObject:jack]);
// 2.判断年龄是否大于25
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"age > 25"];
// 输出为:sunnyzl的年龄是否大于25:1, jack的年龄是否大于25:0
NSLog(@"sunnyzl的年龄是否大于25:%d, jack的年龄是否大于25:%d", [pred2 evaluateWithObject:sunnyzl], [pred2 evaluateWithObject:jack]);

关键方法 evaluateWithObject: 方法返回的是一个BOOL值,如果符合条件YES,不符合NO。

例二:判断手机号是否正确

- (BOOL)checkPhoneNumber:(NSString *)phoneNumber
{NSString *regex = @"^[1][3-8]\\d{9}$";//首数字为1,第二个数字取3~8,具体查看正则表达式(主要用于字符串的搜索)或者【传输门】NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];return [pred evaluateWithObject:phoneNumber];
}

看到这里是不是感觉好爽,感觉以前所有的正则都可以这么匹配,但是谓词匹配正则时也是有缺点的,下面通过一个例子来看一下这个致命的缺点

谓词匹配正则不准确

示例:检测字符串中是否有特殊字符

- (BOOL)checkSpecialCharacter:(NSString *)string
{NSString *regex = @"[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]";NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];return [pred evaluateWithObject:string];
}

按照正则猜想, “!” 应该属于特殊字符

NSString *testString = @"!";
NSLog(@"是否含有特殊字符:%d", [self checkSpecialCharacter:testString]); // 是否含有特殊字符:1// 让我们修改下testString的值
NSString *testString = @"!~";
NSLog(@"是否含有特殊字符:%d", [self checkSpecialCharacter:testString]); // 是否含有特殊字符:0NSString *testString = @"abc!~d";
NSLog(@"是否含有特殊字符:%d", [self checkSpecialCharacter:testString]); // 是否含有特殊字符:0

可以看见,后面两个结果居然是不准确的。

我们会发现谓词对正则并不像我们使用NSRegularExpression时匹配的那么好,究其原因是为什么呢?

我们用NSRegularExpression时会发现匹配到一个结果时就会存入数组,再从匹配到的位置继续向下匹配。然而NSPredicate并不会做这样的自动操作。

我们最终发现在NSPredicate输入[`~!@#$^&*()=|{}':;',\[\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]正则表达式时和写成^[`~!@#$^&*()=|{}':;',\[\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]$的效果是一样的。

总结:谓词 NSPredicate 适合在正则表达式包含首尾(即^表达式$)使用,其他情况建议使用 NSRegularExpression。

2.使用谓词过滤集合

此部分是我们需要掌握的重点,因为从这里我们就可以看到谓词的真正的强大之处

其实谓词本身就代表了一个逻辑条件,计算谓词之后返回的结果永远为BOOL类型的值。而谓词最常用的功能就是对集合进行过滤。当程序使用谓词对集合元素进行过滤时,程序会自动遍历其元素,并根据集合元素来计算谓词的值,当这个集合中的元素计算谓词并返回YES时,这个元素才会被保留下来。请注意程序会自动遍历其元素,它会将自动遍历过之后返回为YES的值重新组合成一个集合返回。

NSArray提供了如下方法使用谓词来过滤集合

- (NSArray*)filteredArrayUsingPredicate:(NSPredicate *)predicate:使用指定的谓词过滤NSArray集合,返回符合条件的元素组成的新集合NSMutableArray提供了如下方法使用谓词来过滤集合
- (void)filterUsingPredicate:(NSPredicate *)predicate:使用指定的谓词过滤NSMutableArray,剔除集合中不符合条件的元素NSSet提供了如下方法使用谓词来过滤集合
- (NSSet*)filteredSetUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSArray中的方法NSMutableSet提供了如下方法使用谓词来过滤集合
- (void)filterUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSMutableArray中的方法。

通过上面的描述可以看出,使用谓词过滤不可变集合和可变集合的区别是:

  • 过滤不可变集合时,会返回符合条件的集合元素组成的新集合;
  • 过滤可变集合时,没有返回值,会直接剔除不符合条件的集合元素

下面让我们来看几个例子:

例一:

NSMutableArray *arrayM = [@[@20, @40, @50, @30, @60, @70] mutableCopy];
// 过滤大于50的值
NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"SELF > 50"];
[arrayM filterUsingPredicate:pred1];
NSLog(@"arrayM:%@", arrayM);
NSArray *array = @[[ZLPersonModel personWithName:@"Jack" age:20 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Rose" age:22 sex:ZLPersonSexFamale],
[ZLPersonModel personWithName:@"Jackson" age:30 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Johnson" age:35 sex:ZLPersonSexMale]];
// 要求取出包含‘son’的元素
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"name CONTAINS 'son'"];
NSArray *newArray = [array filteredArrayUsingPredicate:pred2];
NSLog(@"%@", newArray);
输出为
2016-01-07 16:50:09.510 PredicteDemo[13660:293822] arrayM:(
60,
70
)
2016-01-07 16:50:09.511 PredicteDemo[13660:293822] (
"[name = Jackson, age = 30, sex = 0]",
"[name = Johnson, age = 35, sex = 0]"
)

从这个例子我们就可以看到NSPredicate有强大,避免使用一大堆 if else

让我们来回顾一下上面的从第二个数组中去除第一个数组中相同的元素

例二:

NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
输出为:2016-01-07 13:17:43.669 PredicteDemo[6701:136206] (
a,
abcd
)

如果我们不用NSPredicate的话,肯定又是各种if...else,for循环等等。可以看出NSPredicate的出现为我们节省了大量的时间和精力。

3.在谓词中使用占位符参数

我们上面所有的例子中谓词总是固定的,然而我们在现实中处理变量时决定了谓词应该是可变的。下面我们来看看如果让谓词变化起来。

首先如果我们想在谓词表达式中使用变量,那么我们需要了解下列两种占位符:

%K:用于动态传入属性名
%@:用于动态设置属性值
其实相当于变量名与变量值

除此之外,还可以在谓词表达式中使用动态改变的属性值,就像环境变量一样

1
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS $VALUE"];
上述表达式中,$VALUE是一个可以动态变化的值,它其实最后是在字典中的一个key,所以可以根据你的需要写不同的值,但是必须有$开头,随着程序改变$VALUE这个谓词表达式的比较条件就可以动态改变。

下面我们通过一个例子来看看这三个重要的占位符应该如何使用

例一:

NSArray *array = @[[ZLPersonModel personWithName:@"Jack" age:20 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Rose" age:22 sex:ZLPersonSexFamale],
[ZLPersonModel personWithName:@"Jackson" age:30 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Johnson" age:35 sex:ZLPersonSexMale]];
// 定义一个property来存放属性名,定义一个value来存放值
NSString *property = @"name";
NSString *value = @"Jack";
// 该谓词的作用是如果元素中property属性含有值value时就取出放入新的数组内,这里是name包含Jack
NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", property, value];
NSArray *newArray = [array filteredArrayUsingPredicate:pred];
NSLog(@"newArray:%@", newArray);// 创建谓词,属性名改为age,要求这个age包含$VALUE字符串
NSPredicate *predTemp = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
// 指定$SUBSTR的值为 25 这里注释中的$SUBSTR改为$VALUE
NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @25}];
NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];
NSLog(@"newArray1:%@", newArray1);// 修改 $SUBSTR的值为32, 这里注释中的SUBSTR改为$VALUE
NSPredicate *pred2 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @32}];
NSArray *newArray2 = [array filteredArrayUsingPredicate:pred2];
NSLog(@"newArray2:%@", newArray2);
输出为
2016-01-07 17:28:02.062 PredicteDemo[14542:309494] newArray:(
"[name = Jack, age = 20, sex = 0]",
"[name = Jackson, age = 30, sex = 0]"
)
2016-01-07 17:28:02.063 PredicteDemo[14542:309494] newArray1:(
"[name = Jackson, age = 30, sex = 0]",
"[name = Johnson, age = 35, sex = 0]"
)
2016-01-07 17:28:02.063 PredicteDemo[14542:309494] newArray2:(
"[name = Johnson, age = 35, sex = 0]"
)

从上例中我们主要可以看出来%K和$VALUE的含义。

那么至此NSPredicate就到到此介绍完毕。

NSPredicate的使用相关推荐

  1. NSPredicate

    一.简介 NSPredicate指定数据被获取或者过滤的方式,是一个Foundation类. Cocoa框架中的NSPredicate用于指定过滤器的条件(即查询),它的原理和用法都像SQL的WHER ...

  2. HTTPPost/AFNetWorking/JSONModel/NSPredicate

    一.HTTPPost================================================ 1. POST方式发送请求 HTTP协议下默认数据发送请求方法是GET方式,若需要 ...

  3. IOS NSPredicate 查询、搜索

    简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取. 最常用到的函数 + (NSPredicate *)predicateWith ...

  4. NSPredicate 查询/搜索

    IOS NSPredicate 查询.搜索 简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取. 最常用到的函数 + (NSPre ...

  5. 好用的NSPredicate

    NSPredicate的用法 一般来说这种情况还是蛮多的,比如你从文件中读入了一个array1,然后想把程序中的一个array2中符合array1中内容的元素过滤出来. 正 常傻瓜一点就是两个for循 ...

  6. NSPredicate的用法

    一般来说这种情况还是蛮多的,比如你从文件中读入了一个array1,然后想把程序中的一个array2中符合array1中内容的元素过滤出来. 正 常傻瓜一点就是两个for循环,一个一个进行比较,这样效率 ...

  7. IOS自带正则表达式NSPredicate的使用

    首先举一个例子: 匹配9-15个由字母/数字组成的字符串的正则表达式:     NSString * regex = @"^[A-Za-z0-9]{9,15}$";     NSP ...

  8. iOS之深入解析谓词NSPredicate的语法与应用

    一.简介 NSPredicate 的官方解释如下: The NSPredicate class is used to define logical conditions used to constra ...

  9. 谓词NSPredicate的使用

    谓词是用来为数据添加过滤条件,从而更加精确的找到找到所描述条件的数据.苹果为我们封装好了NSPredicate类,我们可以很方便的得到我们需要的过滤条件. 谓词的简单语法总结: 比较运算: > ...

最新文章

  1. CSS选择器和参考手册
  2. 关于 jest 测试结果如何在浏览器上显示的问题
  3. node / npm 配置问题
  4. java not found_java_home not found in your enviroment 问题解决方法
  5. 今天就唠叨唠叨吧……
  6. ubantu 中配置Flash Player
  7. Java:从99瓶子数到0,一个int、String变量、while循环、if条件测试
  8. 【技术文档】jeecg3.7.1-maven版本搭建环境手把手入门-eclipse
  9. VS code 调试配置01 Debugging
  10. 云小课 | 一个三分钟快速定制OCR应用的神器,要不?
  11. 使用 file_get_contents 获取网站信息报错failed to open stream: HTTP request failed!
  12. 前端,计算中四舍五入保留两位小数操作3中方法
  13. 英文单词乱序后还原 c语言,乱序背单词_有谁也用《不背单词》这个软件吗怎么可以改变背单词的顺序有顺序倒序和乱序的_淘题吧...
  14. 计算机十六进制ABCD,16进制计算(十六进制计算器在线)
  15. 芯片学生党必会的行业英文术语
  16. android 接入百度地图sdk
  17. linux gtx驱动程序,Nvidia 418.43 发布,支持GeForce GTX 1660 Ti的Linux图形驱动程序
  18. MicroPython-On-ESP8266——WIFI与网络
  19. opencv打开摄像头失败的一种可能cv2.error: Unknown C++ exception from OpenCV code
  20. Dashed hopes 破灭的希望,新兴国家的出路在何方?经济学人精读

热门文章

  1. 开发经理 VS 敏捷专家
  2. 值得期待的.Net Micro Framework 3.0
  3. 用国内镜像源pip加速安装模块
  4. Oracle获取LOB长度的两种方法效率对比
  5. ListView详解(二)
  6. httpHandlers使用和问题
  7. 删除Linux的依赖库并进入救援模式恢复
  8. 拷贝构造函数的第一个参数必须是自身类类型的引用
  9. MySQL自学笔记2--select的5个子句
  10. WPF画N角芒星,正N角星