NSPredicate

NSPredicate 是一个Foundation的类,用来定义逻辑条件约束的获取或内存中的过滤搜索,相当于SQL中的where用法。

1.集合中使用 NSPredicate

  • Foundation提供了Predicate来过滤NSArrayNSMutableArrayNSSetNSMutableSetNSDictionary等集合的方法。
  • NSArray&NSSet(不可变集合):通过filteredArrayUsingPredicatefilteredSetUsingPredicate:方法评估一个接收到的predicate来返回一个不可变集合。
  • NSMutableArray&NSMutableSet(可变集合):通过filterUsingPredicate:方法评估一个接收到的predicate来移除评估结果为FALSE的对象,这个可变数组将仅剩下符合要求的对象。同样地,也可以使用filteredArrayUsingPredicatefilteredSetUsingPredicate:方法来过滤返回一个符合要求的不可变集合。
  • NSDictionary:可以使用predicate来过滤分别过滤键值。

CodeSnippest:

1
2
3
4
5
6
7
8
9
10
11
NSMutableArray *mutArr = [NSMutableArray arrayWithObjects:@"bang",@"bing",@"jklb",@"dgjk",nil];
NSLog(@"before filter mutArr is %@",mutArr);
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@",@"g"];

// 可变数组不会被改变,返回一个不可变数组
NSArray *arr = [mutArr filteredArrayUsingPredicate:predicate];
NSLog(@"after filter mutArr is %@,arr is %@",mutArr,arr);

// 可变数组被变更,只剩下符合条件的对象
[mutArr filterUsingPredicate:predicate];
NSLog(@"after filter mutArr is %@",mutArr);

2.谓词语法

  • 替换

%@ 是对值为字符串,数字或者日期的对象的替换值,%K 是key path的替换值

1
2
3
4
5
6
7
// 第一种写法
NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"firstName = 'Bob'"];
NSPredicate *ageIs33Predicate = [NSPredicate predicateWithFormat:@"%K = %@", @"age", @33];

// 第二种写法
NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"@"%K = %@",@"firstName",@"Bob""];
NSPredicate *ageIs33Predicate = [NSPredicate predicateWithFormat:@"age = 33"];

$VARIABLE_NAME是可以被NSPredicate -predicateWithSubstitutionVariables:替换的值。

1
2
3
NSMutableArray *mutArr = [NSMutableArray arrayWithObjects:@"bang",@"bing",@"jklb",@"dgjk",nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] $letter"];
NSLog(@"%@",[mutArr filteredArrayUsingPredicate:[predicate predicateWithSubstitutionVariables:@{@"letter":@"l"}]]);
  • 基本比较 :=(==)、<、>、<=(=<)、>=(=>)、!=(<>)、BETWEEN
1
2
3
NSArray *arr = @[@2,@3,@4,@5];
NSPredicate *arrPredicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {4,10}"];
NSLog(@"%@",[arr filteredArrayUsingPredicate:arrPredicate]);
  • 复合谓词 :AND(&&)、OR(||)、NOT(!)
1
2
3
NSArray *arr = @[@"kezhen",@"bole",@"Archae",@"arphan"];
NSPredicate *arrPredicate = [NSPredicate predicateWithFormat:@"(SELF BEGINSWITH %@) AND (SELF ENDSWITH %@)",@"b",@"e"];
NSLog(@"%@",[arr filteredArrayUsingPredicate:arrPredicate]);
  • 字符串比较相关BEGINSWITH:以指定字符串开始;CONTAINS:包含指定字符串;ENDSWITH:以指定字符串结束;LIKE:左边表达式等于右边表达式,?匹配一个字符,*匹配0个或多个字符;MATCHES:左边的表达式根据ICU v3(更多内容请查看ICU User Guide for Regular Expressions)的regex风格比较,等于右边的表达式。
1
2
3
4
5
6
7
8
9
10
// LIKE
NSArray *arr = @[@"kezhen",@"bole",@"orchan",@"orphan"];
NSPredicate *arrPredicate = [NSPredicate predicateWithFormat:@"SELF LIKE %@",@"?rc*"];
NSLog(@"%@",[arr filteredArrayUsingPredicate:arrPredicate]);

// BETWEEN
NSArray *arr = @[@"kezhen",@"bole",@"Archae",@"arphan"];
NSString *regex = @"^A.+e$"; //以A开头,e结尾
NSPredicate *arrPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
NSLog(@"%@",[arr filteredArrayUsingPredicate:arrPredicate]);
  • 关系操作:ANY、ALL、NONE、IN

3.创建复合谓词

除了用复合谓词关键字连接组合多个谓词,还可以可用以下方法。

1
2
3
4
[NSCompoundPredicate andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"age > 25"], [NSPredicate predicateWithFormat:@"firstName = %@", @"Quentin"]]];

// 使用关键字连接组合多个谓词
[NSPredicate predicateWithFormat:@"(age > 25) AND (firstName = %@)", @"Quentin"];

4.Block谓词

block可以封装任意的计算,所以有一个查询类是无法以NSPredicate格式字符串形式来表达的(比如对运行时被动态计算的值的评估)。

1
2
3
4
NSPredicate *pre = [NSPredicate predicateWithBlock:^BOOL(id  _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [[evaluatedObject firstName] length] < 3;
}];
NSLog(@"firstName.length %@",[arr filteredArrayUsingPredicate:pre]);
坚持原创技术分享,您的支持将鼓励我继续创作!