什么是NSPredicate?
NSPredicate类是用来定义逻辑条件约束的获取或内存中的过滤搜索。通俗的讲谓词是描述事物属性的。在iOS中主要用于查询和检索,如CoreData的数据查询,数组等集合类型的过滤。
- 谓词的分类:比较谓词和复合谓词
- 比较谓词:比较谓词通过使用比较运算符来描述所符合条件的属性状态;
- 复合谓词:用来组合多个比较谓词表达式,去交集、并集、补集;
我们使用NSPredicate都需要定义谓词表达式,而这个表达式必须返回的是BOOL值。
- NSPredicate的创建方式
- 通过格式化字符串创建谓词;
- 通过模板创建谓词;
- 通过代码创建谓词;
- 谓词格式化语法表
运算符 | 意义解释 |
---|---|
==,= | 判断左侧和右侧表达式是否相等 |
!=, <> | 判断左侧和右侧两个表达式是否不相等 |
>=,=> | 判断左侧的值是否大于或等于右侧的值 |
<=,=< | 判断左侧的值是否小于或等于右侧的值 |
> | 判断左侧的值是否大于右侧的值 |
< | 判断左侧的值是否小于右侧的值 |
BETWEEN | 左侧必须在右侧集合的区间中BETWEEN {下限,上限} |
AND,&& | 逻辑与,要求两个表达式的值都为YES时,结果才为YES |
OR,ll | 逻辑或,要求其中一个表达式为YES时,结果就是YES |
NOT,! | 逻辑非,对原有的表达式取反 |
BEGINSWITH | 检查字符串是否以指定的字符串开头 |
ENDSWITH | 检查字符串是否以指定的字符串结尾 |
CONTAINS | 检查某个字符串是否包含指定的字符串 |
LIKE | 检查字符串是否匹配指定的字符串模板,可以与 *和?等通配符可以使用 |
MATCHES | 检查字符串是否匹配指定的正则表达式 |
ANY,SOME | 集合中任意一个元素满足条件,就返回YES |
ALL | 集合中所有元素都满足条件,才返回YES |
NONE | 集合中没有任何元素满足条件就返回YES |
IN | 左边的表达式存在于右边的集合中返回YES |
array[index] | 返回数组中index索引处的元素 |
array[FIRST] | 返回数组中第一个元素 |
array[LAST] | 返回数组中最后一个元素 |
array[SIZE] | 返回数组中元素的个数 |
FALSE,NO | 代表逻辑假 |
TRUE,YES | 代表逻辑真 |
NULL,NIL | 代表空值 |
SELF | 代表需要被验证的对象本身 |
"str",'str' | 代表字符串,""使用时需要转义 |
{'a','b','c' } | 代表数组 |
FALSEPREDICATE | 表示总是返回YES的谓词 |
TRUEPREDICATE | 表示总是返回NO的谓词 |
- 字符串传忽略大小写和忽略重音符
使用谓词检索时对字符串比较运算符需要要不区分大小写和重音符号,就要在这些字符串运算符后使用[c],[d]选项。其中[c]表示不区分大小写,[d]表示不区分重音符号,[cd]表示即忽略大小写又忽略重音符。需要将其写在字符串比较运算符之后,比如:name LIKE[cd] 'string'
- 保留字:大小写都可以使用,推荐使用大写
AND、OR、IN、NOT、ALL、ANY、SOME、NONE、LIKE、CASEINSENSITIVE、CI、MATCHES、CONTAINS、BEGINSWITH、ENDSWITH、BETWEEN、NULL、NIL、SELF、TRUE、YES、FALSE、NO、FIRST、LAST、SIZE、ANYKEY、SUBQUERY、CAST、TRUEPREDICATE、FALSEPREDICATE
NSPredicate的创建
- 通过格式化字符串创建谓词:
- 常用方法:
// Parse predicateFormat and return an appropriate predicate
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat argumetArray:(nullable NSArray *)arguments;
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;
+ (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat arguments:(va_list)argList;
- 使用示例:
NSArray * test = @[@"Herbie",@"Badger",@"Elvis",@"Phoenix",@"Streaker"];
// 检索字符串属性length为5的对象
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"length = 5"];
NSArray * result = [test filteredArrayUsingPredicate:predicate];
// 打印结果
// @[@"Elvis"]
- 说明:
通过格式化字符串创建谓词有多种方式,可以直接使用字符串来创建,如“length = 5”,也可以使用%@、%d、%k等占位符来在运行时替换为变量的实际值,这里着重说下%k,%k用于传入属性名,那为什么设置属性名时不使用%@呢?因为%@在解析时会被解析器自动添加上引号,属性名不需要引号,所以选择使用%k设置属性名,用%@设置属性值。
NSString *key = @"length";
NSString *value = @"5";
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%k = 5", key];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%k = %@", key, value];
-
通过模板创建谓词:
通过模板创建谓词检索,谓词模板中只有键名(属性名),没有键值(属性值),键值在字典中配置提供给模板使用,使用$符号匹配模板和字典中的值。
- 常用方法:
- (instancetype)predicateWithSubstitutionVariables:(NSDictionary<NSString *, id> *)variables;
- 使用示例:
NSDictionary *valueDict = [NSDictionary dictionaryWithObjectsAndKeys:@5, @"LENGTH", nil];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"length = $LENGTH"];
NSArray * test = @[@"Herbie",@"Badger",@"Elvis",@"Phoenix",@"Streaker"];
NSArray * results = [test filteredArrayUsingPredicate:predicate];
// 打印结果
// @[@"Elvis"]
-
通过代码创建谓词:
使用代码创建谓词对象的方式相对于上面两种方式比较复杂,与通过代码创建AutoLayout约束的方式差不多。通过NSComparisonPredicate类创建谓词对象;
- 实现代码
//创建左侧表达式对象 对应为键
NSExpression *leftExpression = [NSExpression expressionForKeyPath:@"length"];
//创建右侧表达式对象 对应为值
NSExpression *rightExpression = [NSExpression expressionForConstantValue:@5];
//创建比较谓词对象
NSComparisonPredicate *predicate = [NSComparisonPredicate predicateWithLeftExpression:leftExpression rightExpression:rightExpression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:NSCaseInsensitivePredicateOption];
NSArray * test = @[@"Herbie",@"Badger",@"Elvis",@"Phoenix",@"Streaker"];
NSArray * results = [test filteredArrayUsingPredicate:predicate];
- NSComparisonPredicateModifier用来进行比较条件的修饰设置
NSDirectPredicateModifier, //直接进行比较操作
NSAllPredicateModifier, //用于数组或集合当内部所有元素都通过验证时集合才算通过
NSAnyPredicateModifier, //同于数组或集合当内部有一个元素满足时集合算通过验证
注意:NSAllPredicateModifier和NSAnyPredicateModifier这两个枚举主要适用于数组和集合类型数据的验证,ALL会验证其中所有元素,全部通过后数组或集合才算验证通过,ANY则只要有一个元素验证通过,数组或集合就算验证通过;
- NSPredicateOperatorType枚举用来设置运算符类型
NSLessThanPredicateOperatorType = 0, // 小于
NSLessThanOrEqualToPredicateOperatorType, // 小于等于
NSGreaterThanPredicateOperatorType, // 大于
NSGreaterThanOrEqualToPredicateOperatorType, // 大于等于
NSEqualToPredicateOperatorType, // 等于、相同
NSNotEqualToPredicateOperatorType, // 不等于、不相同
NSMatchesPredicateOperatorType,// 正则表达式匹配
NSLikePredicateOperatorType, // Like通配符
NSBeginsWithPredicateOperatorType, // 字符串以某个字符串开头
NSEndsWithPredicateOperatorType, // 字符串以某个字符结尾
NSInPredicateOperatorType, // 左边的表达式 出现在右边的集合中
NSCustomSelectorPredicateOperatorType, //使用自定义的函数来进行校验
NSContainsPredicateOperatorType, // 左边的集合包括右边的元素
NSBetweenPredicateOperatorType, // 左边表达式的值在右边的范围中
- NSComparisonPredicateOptions枚举用来设置比较的方式
NSCaseInsensitivePredicateOption, //不区分大小写
NSDiacriticInsensitivePredicateOption, //不区分读音符号
NSNormalizedPredicateOption, //对字符串在比较前进行预处理,替代上面的两个选项,并作出优化
- NSCompoundPredicate类
此类也是NSPredicate的子类,作用是将多个谓词对象复合组合起来进行检索。
//初始化复合谓词
- (instancetype)initWithType:(NSCompoundPredicateType)type subpredicates:(NSArray<NSPredicate *> *)subpredicates;
//快速创建与运算
+ (NSCompoundPredicate *)andPredicateWithSubpredicates:(NSArray<NSPredicate *> *)subpredicates;
//快速创建或运算
+ (NSCompoundPredicate *)orPredicateWithSubpredicates:(NSArray<NSPredicate *> *)subpredicates;
//快速创建非运算
+ (NSCompoundPredicate *)notPredicateWithSubpredicate:(NSPredicate *)predicate;
实际使用
- 数组合集过滤方法:
@interface NSArray<ObjectType> (NSPredicateSupport)
- (NSArray<ObjectType> *)filteredArrayUsingPredicate:(NSPredicate *)predicate;
@end
@interface NSMutableArray<ObjectType> (NSPredicateSupport)
- (void)filterUsingPredicate:(NSPredicate *)predicate;
@end
@interface NSSet<ObjectType> (NSPredicateSupport)
- (NSSet<ObjectType> *)filteredSetUsingPredicate:(NSPredicate *)predicate;
@end
@interface NSMutableSet<ObjectType> (NSPredicateSupport)
- (void)filterUsingPredicate:(NSPredicate *)predicate;
@end
@interface NSOrderedSet<ObjectType> (NSPredicateSupport)
- (NSOrderedSet<ObjectType> *)filteredOrderedSetUsingPredicate:(NSPredicate *)p;
@end
@interface NSMutableOrderedSet<ObjectType> (NSPredicateSupport)
- (void)filterUsingPredicate:(NSPredicate *)p;
@end
- 验证代码
Demo