在现代汉语的解释中,谓词是用来描述或判断客体性质、特征或者客体之间关系的词项。通俗的说,它是描述事物属性的。在iOS开发Cocoa框架中,有提供NSPredicate类,这个类一般也被成为谓词类,其主要的做用是在Cocoa中帮助查询和检索,可是须要注意,实质上谓词并非提供查询和检索的支持,它是一种描述查询检索条件的方式,就像更加标准通用的正则表达式同样。正则表达式
NSPredicate提供的谓词能够分为两类:比较谓词和复合谓词。express
对于比较谓词,能够描述精准的比较也能够经过范围或者包含等进行模糊比较。须要注意,任何Cocoa类对象均可以支持谓词,可是此类须要实现键值编码(key-value-coding)协议。数组
NSPredicate提供建立谓词对象和解析谓词对象的方法,它也是Cocoa中有关谓词的类中的基类。咱们在平常开发中,NSPredicate类的应用频率也最高。框架
建立谓词对象有3种方式,分别是经过格式化字符串建立谓词,直接经过代码建立谓词,经过模板建立谓词。NSPredicate提供了以下函数来进行初始化:函数
//经过格式化字符串来进行谓词对象的初始化 + (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat argumentArray:(nullable NSArray *)arguments; + (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...; + (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat arguments:(va_list)argList;
使用格式化字符串进行谓词的初始化十分灵活,可是须要注意,其谓词字符串的语法和正则表达式并不同,后面会有具体的介绍,下面是一个谓词检索示例:编码
//检索属性length为5的对象 NSPredicate * predicate = [NSPredicate predicateWithFormat:@"length = 5"]; //对于这个数组中的字符串,便是检索字符串长度为5的元素 NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"]; NSArray * result = [test filteredArrayUsingPredicate:predicate]; //将打印@[@"swfas"] NSLog(@"%@",result);
其实,你也能够像使用NSLog函数同样来进行格式化字符串的构造,可使用%@,%d等等格式化字符来在运行时替换为变量的实际值。同时也须要注意,这种格式化字符串建立的谓词语句并不会进行语法检查,错误的语法会产生运行时错误,要格外当心。有一个小细节须要注意,在进行格式化时,若是使用的是变量则不须要添加引号,解析器会帮助你添加,若是使用到常量,则要用转义字符进行转义,例如:lua
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"name = %@ && age = \"25\"",name];
对于属性名,若是也须要进行格式化,须要注意不能使用%@符号,这个符号在解析时会被解析器自动添加上引号,可使用%K,示例以下:spa
NSString * key = @"length"; NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%K = 5",key]; NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"]; NSArray * result = [test filteredArrayUsingPredicate:predicate]; //将打印@[@"swfas"] NSLog(@"%@",result);
经过模板来建立谓词对象也是一种十分经常使用的方式,和格式化字符串不一样的是,谓词模板中只有键名,没有键值,键值须要在字典中进行提供,例如:.net
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"length = $LENGTH"]; predicate = [predicate predicateWithSubstitutionVariables:@{@"LENGTH":@5}]; NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"]; NSArray * result = [test filteredArrayUsingPredicate:predicate]; //将打印@[@"swfas"] NSLog(@"%@",result);
NSPredicate中其余属性与方法解析以下:code
//建立一个老是验证经过(YES)或不经过(NO)的谓词对象 /* 若是建立的是验证经过的,则任何检索都会成功进行返回,不然任何检索都会失败不返回任何对象 */ + (NSPredicate *)predicateWithValue:(BOOL)value; //自定义实现检索函数 /* 例如前面的示例也能够这样写 NSPredicate * predicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) { if ([evaluatedObject length]==5) { return YES; } return NO; }]; */ + (NSPredicate*)predicateWithBlock:(BOOL (^)(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings))block; //格式化字符串属性 @property (readonly, copy) NSString *predicateFormat; //当使用谓词模板来进行对象建立时,这个函数用来设置谓词模板中变量替换 - (instancetype)predicateWithSubstitutionVariables:(NSDictionary<NSString *, id> *)variables; //检查一个Object对象是否能够经过验证 - (BOOL)evaluateWithObject:(nullable id)object; //用谓词模板进行对象的验证 - (BOOL)evaluateWithObject:(nullable id)object substitutionVariables:(nullable NSDictionary<NSString *, id> *)bindings;
前面咱们说有3种建立谓词对象的方式,有两种咱们已经有介绍,经过代码直接建立谓词对象是最复杂的一种。经过代码来建立谓词对象十分相似经过代码来建立Autolayout约束。经过前面咱们的介绍,谓词实际是用表达式来验证对象,用代码来建立谓词实际就是用代码来建立表达式。
这个类是NSPredicate的子类,其用来建立比较类型的谓词。例如使用下面的代码来改写上面的例子:
//建立左侧表达式对象 对应为键 NSExpression * left = [NSExpression expressionForKeyPath:@"length"]; //建立右侧表达式对象 对应为值 NSExpression * right = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:5]]; //建立比较谓词对象 这里设置为严格等于 NSComparisonPredicate * pre = [NSComparisonPredicate predicateWithLeftExpression:left rightExpression:right modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:NSCaseInsensitivePredicateOption]; NSArray * test = @[@"sda",@"321",@"sf12",@"dsdwq1",@"swfas"]; NSArray * result = [test filteredArrayUsingPredicate:pre]; //将打印@[@"swfas"] NSLog(@"%@",result);
NSComparisonPredicateModifier用来进行条件的修饰设置,枚举以下:
typedef NS_ENUM(NSUInteger, NSComparisonPredicateModifier) { NSDirectPredicateModifier = 0, //直接进行比较操做 NSAllPredicateModifier, //用于数组或集合 只有当内部全部元素都经过验证时 集合才算经过 NSAnyPredicateModifier //同于数组或集合 当内部有一个元素知足时 集合算经过验证 };
关于NSAllPredicateModifier和NSAnyPredicateModifier,这两个枚举专门用于数组或集合类型对象的验证,ALL会验证其中全部元素,所有经过后数组或集合才算验证经过,ANY则只要有一个元素验证经过,数组或集合就算验证经过,例如:
NSPredicate * pre = [NSPredicate predicateWithFormat:@"ALL length = 5"]; NSArray * test = @[@[@"aaa",@"aa"],@[@"bbbb",@"bbbbb"],@[@"ccccc",@"ccccc"]]; NSArray * result = [test filteredArrayUsingPredicate:pre]; //将打印@[@[@"ccccc",@"ccccc"]] NSLog(@"%@",result);
NSPredicateOperatorType枚举用来设置运算符类型,以下:
typedef NS_ENUM(NSUInteger, NSPredicateOperatorType) { NSLessThanPredicateOperatorType = 0, // 小于 NSLessThanOrEqualToPredicateOperatorType, // 小于等于 NSGreaterThanPredicateOperatorType, // 大于 NSGreaterThanOrEqualToPredicateOperatorType, // 大于等于 NSEqualToPredicateOperatorType, // 等于 NSNotEqualToPredicateOperatorType, //不等于 NSMatchesPredicateOperatorType, //正则比配 NSLikePredicateOperatorType, //Like匹配 与SQL相似 NSBeginsWithPredicateOperatorType, //左边的表达式 以右边的表达式做为开头 NSEndsWithPredicateOperatorType,//左边的表达式 以右边的表达式做为结尾 NSInPredicateOperatorType, // 左边的表达式 出如今右边的集合中 NSCustomSelectorPredicateOperatorType,//使用自定义的函数来进行 验证 NSContainsPredicateOperatorType, //左边的集合包括右边的元素 NSBetweenPredicateOperatorType //左边表达式的值在右边的范围中 例如 1 BETWEEN { 0 , 33 } };
NSComparisonPredicateOptions枚举用来设置比较的方式,以下:
//若是不须要特殊指定 这个枚举值也能够传0 typedef NS_OPTIONS(NSUInteger, NSComparisonPredicateOptions) { NSCaseInsensitivePredicateOption = 0x01, //不区分大小写 NSDiacriticInsensitivePredicateOption = 0x02,//不区分读音符号 NSNormalizedPredicateOption //比较前进行预处理 代替上面两个选项 };
NSExpression类则是提供建立表达式,下面列出了其中一些方便理解的方法:
//经过格式化字符串建立表达式 + (NSExpression *)expressionWithFormat:(NSString *)expressionFormat argumentArray:(NSArray *)arguments; + (NSExpression *)expressionWithFormat:(NSString *)expressionFormat, ...; + (NSExpression *)expressionWithFormat:(NSString *)expressionFormat arguments:(va_list)argList; //直接经过对象建立常亮的表达式 + (NSExpression *)expressionForConstantValue:(nullable id)obj; //建立变量表达式 验证时将从binding字典中进行替换 + (NSExpression *)expressionForVariable:(NSString *)string; //将多个表达式组合成一个 + (NSExpression *)expressionForAggregate:(NSArray<NSExpression *> *)subexpressions; + (NSExpression *)expressionForUnionSet:(NSExpression *)left with:(NSExpression *)right; + (NSExpression *)expressionForIntersectSet:(NSExpression *)left with:(NSExpression *)right; + (NSExpression *)expressionForMinusSet:(NSExpression *)left with:(NSExpression *)right; + (NSExpression *)expressionForSubquery:(NSExpression *)expression usingIteratorVariable:(NSString *)variable predicate:(NSPredicate *)predicate; //经过预约义的函数和参数数组来构建表达式对象 预约义的函数 可见dev开发文档 + (NSExpression *)expressionForFunction:(NSString *)name arguments:(NSArray *)parameters;
这个类也是NSPredicate类的子类,其使用逻辑关系来组合多个谓词对象,解析以下:
//进行对象初始化 /* typedef NS_ENUM(NSUInteger, NSCompoundPredicateType) { NSNotPredicateType = 0, //取非 NSAndPredicateType, //与运算 NSOrPredicateType, //或运算 }; */ - (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
下面列出了在谓词的格式化字符串规则语法。
语法规则 | 意义 |
= | 左侧等于右侧 |
== | 左侧等于右侧,与=一致 |
>= | 左侧大于等于右侧 |
=> | 左侧大于等于右侧 与 >=一致 |
<= | 左侧小于等于右侧 |
=< | 左侧小于等于右侧 与<=一致 |
> | 左侧大于右侧 |
< | 左侧小于右侧 |
!= | 左侧不等于右侧 |
<> | 左侧不等于右侧 与!=一致 |
BETWEEN | 左侧在右侧的集合中 key BETWEEN @[@1,@2] |
TRUEPREDICATE | 老是返回YES的谓词 |
FALSEPREDICATE | 老是返回NO的谓词 |
AND | 逻辑与 |
&& | 逻辑与 与AND一致 |
OR | 逻辑或 |
|| | 逻辑或 与OR一致 |
NOT | 逻辑非 |
! | 逻辑非 与NOT一致 |
BEGINWITH | 左侧以右侧字符串开头 |
ENDWITH | 左侧以右侧字符串结尾 |
CONTAINS | 左侧集合包含右侧元素 |
LIKE | 左侧等于右侧 而且 *和?等通配符可使用 |
MATCHES | 正则匹配 |
ANY | 对于数组集合类,验证其中任一元素 |
SOME | 同ANY一致 |
ALL | 对于数组集合类,验证其中全部元素 |
NONE | 做用等同于NOT (ANY) |
IN | 左侧在右侧集合中 |
SELF | 被验证的对象自己 |