阅读

NSPredicate 的用法举例

编者按: Cocoa 提供了一个名为NSPredicate的类,用于指定过滤器的条件,用NSPredicate描述查询方式,原理类似于在数据库中进行查询。可以在数据库风格的API中使用NSPredicate类,常见的用于Core Data和Spotlight。

Predicate是一个返回Boolean值的表达式,可以看做是if或while里面的条件表达式,Predicate不依赖于被搜索的具体数据,而是提供一种检索数据的抽象查询定义。 本文讲解过程中用到了部分类比如garage(车库的类),car(车)等仅供举例,未列出创建代码,体会predicate的用法才是关键。

创建Predicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Herbie'"];

计算Predicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"engine.horsepowe > 150"];
NSArray *cars = [garage cars];
for (Car *car in [garage cars]) {
if ([predicate evaluateWithObject:car]) {
NSLog(@"%@",car.name);
}
}

遍历数组取出符合条件的对象。

数组过滤器

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"engine.horsepowe > 150"];
NSArray *results;
results = [cars filteredArrayUsingPredicate:predicate];

假如你有一个可变数组,而且需要剔除不属于该数组的所有项目。使用以下方法:

NSMutableArray *carsCopy = [cars mutableCopy];
[carsCopy filterUsingPredicate:predicate];

构造灵活Predicate

有两种方式,

第一种 格式说明符

NSPredicate *predicate1, *predicate2, *predicate3;

predicate1 = [NSPredicate predicateWithFormat:@"engine.horsepowe > %d",50];

predicate2 = [NSPredicate predicateWithFormat:@"name == %@",@"Herbie"];

predicate3 = [NSPredicate predicateWithFormat:@"%k == %@", @"name", @"Herbie"];

第二种 将变量名放入字符串中,类似于环境变量

此predicate等价于第一种里的的predicate3和predicate2

NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat:@"name == $NAME"];

NSDictionary *varDict;
varDict = [NSDictionary dictionaryWithObjectsAndKeys:@"Herbie",@"NAME", nil];

NSPredicate *predicate = [predicateTemplate predicateWithSubstitutionVariables:varDict];

而此predicate等价于第一种里的predicate1

predicateTemplate = [NSPredicate predicateWithFormat:@"engine.horsepower > $POWER"];

varDict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:150], @"POWER", nil];

predicate = [predicateTemplate predicateWithSubstitutionVariables:varDict];

predicate的运算符

支持C语言的常用运算符 == = > < >= <= != <> && || ! AND OR NOT等

predicate = [NSPredicate predicateWithFormat:@"(engine.horsepower > 50) AND (engine.horsepower < 200)"];
results = [cars filteredArrayUsingPredicate:predicate];

数组运算符

predicate = [NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN{50,200}"];

等价于

NSArray *betweens = [NSArray arrayWithObjects:[NSNumber numberWithInt:50],[NSNumber numberWithInt:200],nil];
predicate = [NSPredicate predicateWithFormat:@"engine.horsepower BEWEEN %@",betweens];

SELF 关键词响应predicate计算对象

NSArray *names1 = [NSArray arrayWithObjects:@"Herbie",@"Badger",@"Judge",@"Elvis", nil];
NSArray *names2 = [NSArray arrayWithObjects:@"Judge",@"Paper Car",@"Badger",@"Phoenix", nil];

predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", names1];
results = [names2 filteredArrayUsingPredicate:predicate];
NSLog(@"%@", results);

答案是:


(
Judge,

Badger

)

字符串运算符

BEGINSWITH 检查某个字符串是否以另一个字符串开头

ENDSWITH 检查某个字符串是否以另一个字符串结尾

CONTAINS 检查某个字符串是否在另一个字符串内部

比如使用 “name BEGINSWITH ‘Bad’ “ 匹配Badger
匹配是区分大小写的,如果匹配BADGer就匹配不得了

要忽视大小写及重音符等规则,可以前面加上[cd]
“ name BEGINSWITH [cd] ‘HERB’ “ 匹配 Herbie 即可匹配成功 ,通常加上[cd]比较好

LIKE运算符

“ name LIKE ‘ er ‘ “将会与任何含有er的名称匹配,等价于CONTAINS
“ name LIKE ‘ ???er* ‘ “将会与Paper Car 匹配 但不会与Badger匹配,er前面限定了三个字符
如果你热衷于正则表达式,可以使用MATCHES 运算符,赋给它一个正则表达式。

CoreData Prdicate 支持的运算符和参数

Basic Comparisons: =, ==, >=, =>, <=, =<, >, <, !=, <>, BETWEEN{low, high}

Boolean: AND (&&), OR(||), NOT(!)

String: BEGINSWITH, CONTSINS, ENDSWITH, LIKE, MATCHES

Aggregate: ANY, SOME, ALL, NONE, IN

Literals: FALSE, NO, TRUE, YES, NULL, NIL, SELF. (Core data 还支持字符串和数字字面量)


鼓励一下

如果觉得我的文章对您有用,请土豪扫右侧二维码打赏2块钱,帮我买杯咖啡,您的支持将鼓励我继续创作!”


关于Kovli Studio

Kovli Studio是本人全栈开发历程中部分作品的展示平台。作品从衣食住行娱乐等各角度为用户提供实用、高品质、高颜值、高性价比的品质生活方案,欢迎使用。