NSPredicate 朱雀 2022-08-21 02:26 3阅读 0赞 转载地址: https://segmentfault.com/a/1190000000623005 大家在平常的开发过程中多多少少都会接触到数据筛选,那势必会用到`NSPredicate`,这个类和我上一篇博文中提到的[valueForKeyPath][]一样很强大。它的使用主要集中在两个方法中 #### NSArray #### - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate; #### NSMutableArray #### - (void)filterUsingPredicate:(NSPredicate *)predicate; 还有`NSSet`和`NSMutableSet`也可以用这个类筛选。 下面我就来一一介绍这个类的用法,相信大家看完后会和我一样认为这个类真的很强大。 # 筛选用法 # * 利用成员实例方法 筛选出长度大于3的字符串 NSArray *array = @[@"jim", @"cook", @"jobs", @"sdevm"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"length > 3"]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]); 打印 ( cook, jobs, sdevm ) `lenght`就是对数组成员执行\[xxxx lenght\]然后判断返回的NSUInteger值是否大于3。扩展到NSString其他方法比如`integerValue` NSArray *array = @[@"2", @"3", @"4", @"5"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"integerValue >= %@", @3]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]); 如果我不想用任何实例方法,想筛选成员本身应该怎么做呢。这时候就可以用`self`来代替 NSPredicate *pre = [NSPredicate predicateWithFormat:@"self CONTAINS %@", @3]; `CONTAINS`用法后面会讲到 再扩展到模型 > Test.h @interface Test : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSNumber *code; @end Test *test1 = [[Test alloc]init]; test1.name = @"西湖"; test1.code = @1; Test *test2 = [[Test alloc]init]; test2.name = @"西溪湿地"; test2.code = @2; Test *test3 = [[Test alloc]init]; test3.name = @"灵隐寺"; test3.code = @3; NSArray *array = @[test1, test2, test3]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"code >= %@", @2]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]); 筛选出数组成员`[test code]`方法(code属性的get方法)返回值>=2的成员。这里的比较运算符同样也可以使用`==`、`!=`、`<=`、`<`。 其实`==`不仅可以用来比较NSNumber对象,还可以用来判断NSString对象是否相同。 NSPredicate *pre = [NSPredicate predicateWithFormat:@"name == %@", @"西湖"]; 筛选出`name`是"西湖"的对象数组。 * \#\#\#NSString对象的操作 前面提到`==`比较运算符可以起到`- (BOOL)isEqualToString:(NSString *)aString;`方法的效果,来判断字符串是否相同。那么字符串中包含某个字符串应该如何判断呢,在NSPredicate中可以用`CONTAINS`(大小写都可以)来表示包含关系。 NSPredicate *pre = [NSPredicate predicateWithFormat:@"name CONTAINS %@", @"湖"]; 当判断的时候需要忽略大小写可以使用`[cd]` > #### \[c\] 忽略大小写 #### #### \[d\] 忽略重音符号 #### #### \[cd\]既不区分大小写,也不区分发音符号。 #### 使用: NSPredicate *pre = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", @"abc"]; 再涉及到一些更复杂的查询语句,比如判断字符串以某个字符串开头或者结尾,通配符的使用。 #### `BEGINSWITH(已某个字符串开头, begins with)` #### NSString *targetString = @"h"; NSPredicate *pre = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@",targetString]; #### `ENDSWITH(已某个字符串结尾, ends with)` #### NSString *targetString = @"ing"; NSPredicate *pre = [NSPredicate predicateWithFormat:@"name ENDSWITH %@",targetString]; #### `通配符 LIKE` #### > #### \*代表一个或者多个或者是空 #### #### ?代表一个字符 #### Test *test1 = [[Test alloc]init]; test1.name = @"absr"; test1.code = @1; Test *test2 = [[Test alloc]init]; test2.name = @"asb"; test2.code = @2; Test *test3 = [[Test alloc]init]; test3.name = @"raskj"; test3.code = @3; NSArray *array = @[test1, test2, test3]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"name LIKE %@", @"?b*"]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]); 结果是只有test1符合,`like`也可以接受`[cd]` NSPredicate *pre = [NSPredicate predicateWithFormat:@"name LIKE[cd] %@", @"?b*"]; #### 关系运算,包括了`IN`、`BETWEEN`、`AND`、`OR`、`NOT` #### #### `IN(之中)` #### NSPredicate *pre = [NSPredicate predicateWithFormat:@"code IN %@", @[@1, @3]]; 判断code是否@1或者是@2,也就是是否在数组中。 #### `OR(或,可以用||代替)` #### `OR`可以用来代替`IN`达到同样的效果,但是`OR`更灵活。 NSPredicate *pre = [NSPredicate predicateWithFormat:@"code == %@ OR code == %@ ", @1, @3]; 效果和`IN`一样,但是`OR`可以判断不只一个属性 NSPredicate *pred = [NSPredicate predicateWithFormat:@"code == %@ OR name == %@ ", @1, @"asb"]; #### `BETWEEN(之间)` #### 通常用于判断NSNumber对象 NSPredicate *pred = [NSPredicate predicateWithFormat:@"code BETWEEN {1, 3}"]; 判断code是否>=1且<=3 #### `AND(且,可以用&&代替)` #### NSPredicate *pred = [NSPredicate predicateWithFormat:@"code >= %@ AND code <=%@", @1, @3]; #### `NOT(非,可以用!代替)` #### `NOT`最常见的用法就是从一个数组中剔除另外一个数组的数据,可能有点绕,举个例子就很明朗了。 NSArray *arrayFilter = @[@"abc1", @"abc2"]; NSArray *arrayContent = @[@"a1", @"abc1", @"abc4", @"abc2"]; NSPredicate *thePredicate = [NSPredicate predicateWithFormat:@"NOT (SELF in %@)", arrayFilter]; NSLog(@"%@",[arrayContent filteredArrayUsingPredicate:thePredicate]); 打印 ( a1, abc4 ) 比起循环比较再加到新数组中,简单的不止一两点。 #### 前面提到的都是用`+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;`方法创建,还有另一种常用的方法:`+ (NSPredicate*)predicateWithBlock:(BOOL (^)(id evaluatedObject, NSDictionary *bindings))block`,用Block形式创建 #### NSPredicate *pre = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { Test *test = (Test *)evaluatedObject; if (test.code.integerValue > 2) { return YES; } else{ return NO; } }]; 参数`evaluatedObject`表示数组成员,block必须返回YES或者NO,分别表示匹配还是不匹配。请忽略`bindings`参数,具体作用我也没搞清楚。 ### 多重筛选 ### 如果需要匹配数个属性的筛选,用`AND`或者`OR`来串联显然有点麻烦,`NSCompoundPredicate`类可以满足我们的需求,它可以将多个`NSPredicate`对象的组合,组合方式可以是`AND`或者`OR`。 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]]; # 匹配用法 # #### 其实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}"; # 坑 # 不得不说,在利用`+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;`方法创建的NSPredicate对象的时候有个坑。 在某些情况下,类似于上面例子中的`code`字符串不是很明确,创建的时候就会这样使用 Test *test1 = [[Test alloc]init]; test1.name = @"absr"; test1.code = @1; Test *test2 = [[Test alloc]init]; test2.name = @"asb"; test2.code = @2; Test *test3 = [[Test alloc]init]; test3.name = @"raskj"; test3.code = @3; NSArray *array = @[test1, test2, test3]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"%@ == %@", @"code", @2]; NSLog(@"%@", [array filteredArrayUsingPredicate:pre]); 注意NSPredicate对象的初始化方式。运行这块代码你会发现test2对象没有被查询出来。打印`pre`发现`"code" == 2`,这说明查找的是`"code"`方法的返回值,这显然行不通。 #### 如果查询的是属性,比如code是Test类的属性,那么利用下面的创建方式 #### NSPredicate *pre = [NSPredicate predicateWithFormat:@"%K == %@", @"code", @2]; 就不会被坑 #### 注意:`%K`的`K`必须是大写。 #### # 最后 # NSPredicate几乎可以满足所有形式的查询,配合Core Data的数据库查询当然不在话下。NSPredicate用法不只这些,有兴趣的同学可以看下nshipster网站的这篇[博文][Link 1],里面提到了一些我没有涉及到的用法。 [valueForKeyPath]: http://bawn.github.io/blog/2014/05/07/valueForKeyPath/ [Link 1]: http://nshipster.com/nspredicate/
相关 华山论剑之iOS NSPredicate(谓词)的使用(二) [华山论剑之iOS NSPredicate(谓词)的使用(一)][iOS NSPredicate] 在上篇的博客中 ,我提到了谓词的简单使用,主要用于我们对数据的筛选,比 你的名字/ 2023年01月05日 05:03/ 0 赞/ 188 阅读
相关 华山论剑之iOS NSPredicate(谓词)的使用(一) 谓词? 谓词在我们的iOS开发过程中是必不可少的,谓词的作用主要是筛选过滤,提供的数据不能满足我们的需求的时候,我们就需要进行筛选过滤.再说如何使用谓词之前 我要先说一下在谓词 港控/mmm°/ 2023年01月05日 05:02/ 0 赞/ 124 阅读
相关 iOS Predicate Format String Syntax 【NSPredicate在正则表达式的应用】 文章目录 引言 I、iOS Predicate Format String Syntax 1.1 Parser Basics 1.2 ゝ一世哀愁。/ 2022年11月17日 03:40/ 0 赞/ 11 阅读
相关 iOS数据搜索技巧之【利用正则表达式进行匹配查找数据 】1、使用正则表达式对聊天记录的关键词进行监控 2、NSPredicate在正则表达式的应用 文章目录 引言 I、【使用正则表达式对聊天记录的关键词进行监控】 II iOS Predicate Format String Syntax 【NSPr た 入场券/ 2022年10月25日 14:22/ 0 赞/ 3 阅读
相关 iOS NSPredicate的应用指南之【从数组搜索特定条件的元素】(从数组中筛选type=8的电子签名数据,避免遍历数组 certificateInfoList) 文章目录 前言 I、从数组搜索特定条件的元素 1.0 筛选选中的规格数据 1.1 将含有日期属性的对象数组按照日期重新分组 ╰+攻爆jí腚メ/ 2022年10月25日 14:16/ 0 赞/ 61 阅读
相关 NSPredicate 转载地址: https://segmentfault.com/a/1190000000623005 大家在平常的开发过程中多多少少都会接触到数据筛选,那势 朱雀/ 2022年08月21日 02:26/ 0 赞/ 4 阅读
相关 正则表达式详解——NSRegularExpression类和NSPredicate类的使用 在网上查询了一些资料,有张图解释的非常详细,如下所示: ![Center][] NSPredicate类 即谓词已将整理过了,在此主要总结学习过的专门用于正则表达式 港控/mmm°/ 2022年08月09日 01:52/ 0 赞/ 170 阅读
相关 NSString拼接字符串和NSPredicate详解 <table style="padding:0px!important; margin:0px!important; border-width:0px!important; b 小咪咪/ 2021年09月11日 04:40/ 0 赞/ 322 阅读
还没有评论,来说两句吧...