一、简介

  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关系操作

  • ANYSOME:指定下列表达式中的任意元素。比如,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)来过滤NSArrayNSMutableArray&NSSetNSMutableSet的方法。

  对不可变的集合(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可以由过滤的NSArrayNSSet生成一个新的有序的集,或者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相关推荐

  1. NSPredicate的使用

    NSpredicate介绍 首先,我们需要知道什么是谓词,让我们看看官方的解释: The NSPredicate class is used to define logical conditions ...

  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. MySQL高可用群集------配置MMM高可用架构
  2. Idea(二) 解决IDEA卡顿问题及相关基本配置(转)
  3. 《ES6标准入门》49~68Page 数值的拓展 数组的拓展
  4. django mysql内存泄漏_Django的:使内存的关系,而不保存到数据库
  5. 初学者:如何使用虚拟PC将Windows 7安装到虚拟机
  6. 初一模拟赛总结(4.7)
  7. 暗黑破坏神(ssl 2295)
  8. 5000并发的qps是多少_高并发架构设计
  9. csdn飞鸽传书 打了七天七夜
  10. 甘特图制作_使用excel制作甘特图其实很简单,仅需4步搞定,项目进度一目了然...
  11. Python import其他文件夹的文件
  12. 图像处理-与,或等运算
  13. 开源OA协同办公平台搭建教程丨模糊人员匹配功能配置说明
  14. 谷歌金山词霸/搜狗、QQ、google输入法模式分析及展望
  15. 固态硬盘能不能提高计算机速度,固态硬盘掉速如何解决?几招轻松提升SSD速度方法 (全文)...
  16. windows10桌面图标异常,显示为白色图标
  17. YunEngine SDK已经开始发放了!!!
  18. 小程序 function(res)与(res) =的区别
  19. 相当不错的在线用户故事地图绘制工具
  20. 安装pip最新版 20.1

热门文章

  1. Java I/O Demo
  2. PostgreSQL 编译安装
  3. 总结—elasticsearch启动失败的几种情况及解决
  4. Linux内存管理原理【转】
  5. ZIL (ZFS intent log) zil.c
  6. 科技公司高管职位知多少?(转)
  7. Microsoft Expression Blend 2 密钥,key
  8. 使用定制的NSDictionary的方法,对NSArray进行排序(附:数组排序两种常见方法)
  9. 软件公司因女员工怀二胎拒绝与其续约
  10. 全球只有4个人通关的游戏!不过如此