Cocoa中谓词(Predicate)提供了一个通用的查询方式处理数据,可以获取和指定数据的过滤形式,Cocoa实际开发中可以是使用NSPredicate及其父类NSComparisonPredicate和NSCompoundPredicate.其风格类似于SQL查询语言和正则表达式的混合体,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。一般来说稍微操作过数据库基本上很容易理解其中的方法,至于使用的方法也很简单。
首先来一段比较简单的代码:
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", @[@"keso", @"FlyElephant", @"博客园"]];
- if ([predicate evaluateWithObject:@"keso"]) {
- NSLog(@"keso");
- };
第一行代码初始化一个查询条件,第二句就是判断数据在不在结果集中,跟SQL基本上一样,通过IN就能大概了解其功能,SELF表示本身,非常常用。
接下来可以类似于SQL中like语句的代码:
- NSArray *array = [[NSArray alloc]initWithObjects:@"北京",@"上海",@"广州",@"深圳",nil];
- NSPredicate *preBegin= [NSPredicate predicateWithFormat:@"SELF beginswith[c] %@",@"北"];
- NSPredicate *preContain= [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"海"];
- NSLog(@"%@",[array filteredArrayUsingPredicate:preBegin][0]);
- NSLog(@"%@",[array filteredArrayUsingPredicate:preContain][0]);
第一次就是先初始化数组,然后创建条件,通过filteredArrayUsingPredicate过滤数组;
NSDictionary可以用谓词来过滤它的键和值(两者都为NSArray对象);
NSOrderedSet可以由过滤的NSArray或NSSet生成一个新的有序的集,或者NSMutableSet可以简单的removeObjectsInArray来传递通过否定predicate过滤的对象。
NSPredicate
谓词的在Core Data同样适用,在管理对象环境中,谓词由持久化存储助理(persistent store coordinator)评估,而集合则是内存中过滤。这时候我们有必要里了解一下基本比较运算符:
- NSPredicate *betweenPredicate =
- [NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];
- NSDictionary *dictionary = @{ @"attributeName" : @5 };
- BOOL between = [betweenPredicate evaluateWithObject:dictionary];
- if (between) {
- NSLog(@"比较运算符between");
- }
- NSString *regex = @"[A-Za-z]+";
- NSPredicate *matchpredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
- if ([matchpredicate evaluateWithObject:@"keso"]) {
- NSLog(@"匹配成功");
- }
- @interface People : NSObject
- @property (strong,nonatomic) NSString *FirstName;
- @property (strong,nonatomic) NSString *LastName;
- @property (nonatomic) NSInteger Height;
- - (NSString *)description;
- @end
People.m文件:
- @implementation People
- - (NSString *)description {
- return [NSString stringWithFormat:@"%@%@",self.LastName, self.FirstName];
- };
- @end
具体实现代码:
- NSArray *firstNames =[[NSArray alloc]initWithObjects:@"泽东", @"恩来", @"介石", @"中山", nil];
- NSArray *lastNames = @[ @"毛", @"周", @"蒋", @"孙" ];
- NSArray *familiar = @[ @100, @99, @99, @98 ];
- NSMutableArray *dataList= [NSMutableArray array];
- [firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
- People *people= [[People alloc] init];
- people.FirstName = firstNames[idx];
- people.LastName = lastNames[idx];
- people.Height= [familiar[idx] integerValue];
- [dataList addObject:people];
- }];
- NSPredicate *firstPredicate = [NSPredicate predicateWithFormat:@"FirstName = '恩来'"];
- NSPredicate *lastPredicate = [NSPredicate predicateWithFormat:@"LastName = %@", @"蒋"];
- NSPredicate *heightPredicate = [NSPredicate predicateWithFormat:@"Height < 99"];
- //名搜索
- NSLog(@"名: %@",[dataList filteredArrayUsingPredicate:firstPredicate][0]);
- //姓搜索
- NSLog(@"姓: %@", [dataList filteredArrayUsingPredicate:lastPredicate][0]);
- //知名度
- NSLog(@"知名度: %@", [dataList filteredArrayUsingPredicate:heightPredicate][0]);
其实开始讲的NSCompoundPredicate和
NSComparisonPredicate,因为有关系操作,基本上类似,如果通过混合搜索可以使用and,or实现,比如一下代码是等价的:
- NSCompoundPredicate *comPredicate=[NSCompoundPredicate andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"Height > 90"], [NSPredicate predicateWithFormat:@"FirstName = %@", @"介石"]]];
- NSPredicate *secondPredicate=[NSPredicate predicateWithFormat:@"(Height > 90) AND (FirstName = %@)", @"介石"];
NSComparisonPredicate有两个调用的静态方法:
- + (NSComparisonPredicate *)predicateWithLeftExpression:(NSExpression *)lhs rightExpression:(NSExpression *)rhs modifier:(NSComparisonPredicateModifier)modifier type:(NSPredicateOperatorType)type options:(NSComparisonPredicateOptions)options;
- + (NSComparisonPredicate *)predicateWithLeftExpression:(NSExpression *)lhs rightExpression:(NSExpression *)rhs customSelector:(SEL)selector;
其实就是一个表达式的拼接的过程,不过具体的实现苹果给封装好了,一下是NSPredicateOperatorType类型:
- typedef NS_ENUM(NSUInteger, NSPredicateOperatorType) {
- NSLessThanPredicateOperatorType = 0, // compare: returns NSOrderedAscending
- NSLessThanOrEqualToPredicateOperatorType, // compare: returns NSOrderedAscending || NSOrderedSame
- NSGreaterThanPredicateOperatorType, // compare: returns NSOrderedDescending
- NSGreaterThanOrEqualToPredicateOperatorType, // compare: returns NSOrderedDescending || NSOrderedSame
- NSEqualToPredicateOperatorType, // isEqual: returns true
- NSNotEqualToPredicateOperatorType, // isEqual: returns false
- NSMatchesPredicateOperatorType,
- NSLikePredicateOperatorType,
- NSBeginsWithPredicateOperatorType,
- NSEndsWithPredicateOperatorType,
- NSInPredicateOperatorType, // rhs contains lhs returns true
- NSCustomSelectorPredicateOperatorType,
- NSContainsPredicateOperatorType NS_ENUM_AVAILABLE(10_5, 3_0) = 99, // lhs contains rhs returns true
- NSBetweenPredicateOperatorType NS_ENUM_AVAILABLE(10_5, 3_0)
- };
参考资料:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-SW1