一、引言
在现代汉语的解释中,谓词是用来描述或判断客体性质、特征或者客体之间关系的词项。通俗的说,它是描述事物属性的。在iOS开发Cocoa框架中,有提供NSPredicate类,这个类通常也被成为谓词类,其主要的作用是在Cocoa中帮助查询和检索,但是需要注意,实质上谓词并不是提供查询和检索的支持,它是一种描述查询检索条件的方式,就像更加标准通用的正则表达式一样。
NSPredicate提供的谓词可以分为两类:比较谓词和复合谓词。
比较谓词:比较谓词通过使用比较运算符来描述所符合条件的属性状态。
复合谓词:复合谓词用来组合多个比较谓词的结果,取交集,并集或补集。
对于比较谓词,可以描述精准的比较也可以通过范围或者包含等进行模糊比较。需要注意,任何Cocoa类对象都可以支持谓词,但是此类需要实现键值编码(key-value-coding)协议。
二、NSPredicate类的应用解析
NSPredicate提供创建谓词对象和解析谓词对象的方法,它也是Cocoa中有关谓词的类中的基类。我们在日常开发中,NSPredicate类的应用频率也最高。
创建谓词对象有3种方式,分别是通过格式化字符串创建谓词,直接通过代码创建谓词,通过模板创建谓词。NSPredicate提供了如下函数来进行初始化:
//通过格式化字符串来进行谓词对象的初始化
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat argumentArray:(nullable NSArray *)arguments;
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat arguments:(va_list)argList;
使用格式化字符串进行谓词的初始化十分灵活,但是需要注意,其谓词字符串的语法和正则表达式并不一样,后面会有具体的介绍,下面是一个谓词检索示例:
//检索属性length为5的对象
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"length = 5"];
//对于这个数组中的字符串,即是检索字符串长度为5的元素
NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"];
NSArray * result = [test filteredArrayUsingPredicate:predicate];
//将打印@[@"swfas"]
NSLog(@"%@",result);
其实,你也可以像使用NSLog函数一样来进行格式化字符串的构造,可以使用%@,%d等等格式化字符来在运行时替换为变量的实际值。同时也需要注意,这种格式化字符串创建的谓词语句并不会进行语法检查,错误的语法会产生运行时错误,要格外小心。有一个小细节需要注意,在进行格式化时,如果使用的是变量则不需要添加引号,解析器会帮助你添加,如果使用到常量,则要用转义字符进行转义,例如:
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"name = %@ && age = \"25\"",name];
对于属性名,如果也需要进行格式化,需要注意不能使用%@符号,这个符号在解析时会被解析器自动添加上引号,可以使用%K,示例如下:
NSString * key = @"length";
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%K = 5",key];
NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"];
NSArray * result = [test filteredArrayUsingPredicate:predicate];
//将打印@[@"swfas"]
NSLog(@"%@",result);
通过模板来创建谓词对象也是一种十分常用的方式,和格式化字符串不同的是,谓词模板中只有键名,没有键值,键值需要在字典中进行提供,例如:
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"length = $LENGTH"];
predicate = [predicate predicateWithSubstitutionVariables:@{@"LENGTH":@5}];
NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"];
NSArray * result = [test filteredArrayUsingPredicate:predicate];
//将打印@[@"swfas"]
NSLog(@"%@",result);
NSPredicate中其他属性与方法解析如下:
//创建一个总是验证通过(YES)或不通过(NO)的谓词对象
/*
如果创建的是验证通过的,则任何检索都会成功进行返回,否则任何检索都会失败不返回任何对象
*/
+ (NSPredicate *)predicateWithValue:(BOOL)value;
//自定义实现检索函数
/*
例如前面的示例也可以这样写
NSPredicate * predicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
if ([evaluatedObject length]==5) {
return YES;
}
return NO;
}];
*/
+ (NSPredicate*)predicateWithBlock:(BOOL (^)(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings))block;
//格式化字符串属性
@property (readonly, copy) NSString *predicateFormat;
//当使用谓词模板来进行对象创建时,这个函数用来设置谓词模板中变量替换
- (instancetype)predicateWithSubstitutionVariables:(NSDictionary<NSString *, id> *)variables;
//检查一个Object对象是否可以通过验证
- (BOOL)evaluateWithObject:(nullable id)object;
//用谓词模板进行对象的验证
- (BOOL)evaluateWithObject:(nullable id)object substitutionVariables:(nullable NSDictionary<NSString *, id> *)bindings;