NSPredicate的使用

时间:2023-03-10 06:13:54
NSPredicate的使用

简述

NSPredicate谓词条件过滤器,一般用于过滤数组数据,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取。

常用函数

  1. 创建谓词
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;
  1. 使用谓词过滤集合
  • NSarray过滤
//使用指定的谓词过滤NSArray集合,返回符合条件的元素组成的新集合
- (NSArray*)filteredArrayUsingPredicate:(NSPredicate *)predicate;
  • NSMutableArray过滤
//使用指定的谓词过滤NSMutableArray,剔除集合中不符合条件的元素
- (void)filterUsingPredicate:(NSPredicate *)predicate;
  • NSSet过滤
- (NSSet*)filteredSetUsingPredicate:(NSPredicate *)predicate;

  • NSMutableSet过滤
- (void)filterUsingPredicate:(NSPredicate *)predicate;

  • NSOrderedSet过滤
- (NSOrderedSet<ObjectType> *)filteredOrderedSetUsingPredicate:(NSPredicate *)p;

  • NSMutableOrderedSet过滤
- (void)filterUsingPredicate:(NSPredicate *)p;

使用

创建模型类Person,包含nameage两个属性

初始化数据源数组

	Person *person1 = [Person initWithName:@"alex" andAge:22];
Person *person2 = [Person initWithName:@"ceciliaba" andAge:35];
Person *person3 = [Person initWithName:@"1" andAge:42];
Person *person4 = [Person initWithName:@"otto" andAge:18];
Person *person5 = [Person initWithName:@"yasha2" andAge:16]; NSArray *personArr = [NSArray arrayWithObjects:person1,person2,person3,person4,person5, nil];

定义谓词对象,设置过滤条件(过滤条件中,使用self.name和直接用name的效果一样)

//age小于30
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age<30"]; //查询name=1的并且age大于40
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name='1' && age>40"]; //name以a开头的
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'a'"]; //name以ba结尾的
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name ENDSWITH 'ba'"]; //name为1/2/4,或者age在30-40之间的
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name IN {'1','2','4'} || age between{30,40}"]; //like 匹配任意多个字符
//name中只要有s字符就满足条件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like '*s*'"]; //?代表一个字符,下面的查询条件是:name中第二个字符是s的 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like '?s'"];

使用谓词条件过滤数组中的元素,过滤之后返回查询的结果

NSArray *array = [personArr filteredArrayUsingPredicate:predicate];  

使用占位符,动态修改条件

在使用时,如果需要拼接属性名,其占位符为%K(注意大写)而不是%@,如:

NSString * key = @"age";
int age = 30;
//拼接示例:
[NSPredicate predicateWithFormat:@"%K < %d", key, age];

如果想动态改变判断的范围,可以使用$ 开头的占位符:

//用$AGE进行占位,可以动态修改$对应的值,这里的AGE可以是任意字符串
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < $AGE"]; //修改AGE的值(AGE对应上面的$后的字符串),生成新的NSPredicate对象
NSPredicate *newPredicate = [predicate predicateWithSubstitutionVariables:@{@"AGE":@30}]; //使用newPredicate过滤数组
NSArray *array = [persons filteredArrayUsingPredicate: newPredicate];

使用附加符号增加规则

附加符号:[c] [d] [cd] c表示不区分大小写,d表示不区分发音字符,cd表示什么都不区分

错误用法

    NSArray *array = [NSArray arrayWithObjects:@{@"city":@"beijing"},@{@"city":@"shanghai"},@{@"city":@"guangzhou"},@{@"city":@"wuhan"}, nil];
NSString *string = @"ang"; NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@",string];
NSMutableArray *tempArr = [NSMutableArray new];
for (NSDictionary *dic in array) {
if ([pred evaluateWithObject:dic[@"city"]]) {
[tempArr addObject:dic];
}
}
NSLog(@"tempArr = %@",tempArr); 输出:
tempArr = (
{
city = shanghai;
},
{
city = guangzhou;
}
)

这种用法虽然也能过滤出想要的数据,但是效率不高,后面的for循环其实可以省略的

正确用法


NSPredicate *pred = [NSPredicate predicateWithFormat:@"city CONTAINS[cd] %@",string];
NSArray *resultArr = [array filteredArrayUsingPredicate:pred];
NSLog(@"resultArr = %@",resultArr); 输出:
resultArr = (
{
city = shanghai;
},
{
city = guangzhou;
}
)