iOS开发-NSPredicate
Cocoa中谓词(Predicate)提供了一个通用的查询方式处理数据,可以获取和指定数据的过滤形式,Cocoa实际开发中可以是使用NSPredicate及其父类NSComparisonPredicate和NSCompoundPredicate.其风格类似于SQL查询语言和正则表达式的混合体,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。一般来说稍微操作过数据库基本上很容易理解其中的方法,至于使用的方法也很简单。 集合中的NSPredicate Foundation提供使用谓词(predicate)来过滤NSArray/NSMutableArray&NSSet/NSMutableSet的方法。 不可变的集合,NSArray&NSSet,可以通过评估接收到的predicate来返回一个不可变集合的方法filteredArrayUsingPredicate和filteredSetUsingPredicate; 可变集合,NSMutableArray&NSMutableSet,可以使用方法filterUsingPredicate:可以通过运行接收到的谓词来移除评估结果为FALSE的对象。 首先来一段比较简单的代码: 1 2 3 4 NSPredicate *predicate = [ NSPredicate predicateWithFormat:@ "SELF IN %@" , @[@ "keso" , @ "FlyElephant" , @ "博客园" ]]; if ([predicate evaluateWithObject:@ "keso" ]) { NSLog (@ "keso" ); }; 第一行代码初始化一个查询条件,第二句就是判断数据在不在结果集中,跟SQL基本上一样,通过IN就能大概了解其功能,SELF表示本身,非常常用。 接下来可以类似于SQL中like语句的代码: 1 2 3 4 5 6 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过滤的对象。 Core Data中的NSPredicate 谓词的在Core Data同样适用,在管理对象环境中,谓词由持久化存储助理(persistent store coordinator)评估,而集合则是内存中过滤。这时候我们有必要里了解一下基本比较运算符: =, ==:左边的表达式和右边的表达式相等。 >=, =>:左边的表达式大于或者等于右边的表达式。 <=, =<:左边的表达式小于等于右边的表达式。 >:左边的表达式大于右边的表达式。 <:左边的表达式小于右边的表达式。 !=, <>:左边的表达式不等于右边的表达式。 BETWEEN:左边的表达式等于右边的表达式的值或者介于它们之间。右边是一个有两个指定上限和下限的数值的数列(指定顺序的数列)。比如,1 BETWEEN { 0 , 33 },或者INPUTBETWEEN{INPUTBETWEEN{LOWER, $UPPER }。可参考以下代码: 1 2 3 4 5 6 7 8 9 NSPredicate *betweenPredicate = [ NSPredicate predicateWithFormat: @ "attributeName BETWEEN %@" , @[ @1 , @10 ]]; NSDictionary *dictionary = @{ @ "attributeName" : @5 }; BOOL between = [betweenPredicate evaluateWithObject:dictionary]; if (between) { NSLog (@ "比较运算符between" ); } 基本复合谓词 AND, &&:逻辑与. OR, ||:逻辑或. NOT, !:逻辑非 字符串比较 字符串比较非常常用,以下的都应该比较熟悉: BEGINSWITH[cd] $FIRST_NAME。 BEGINSWITH:左边的表达式以右边的表达式作为开始。 CONTAINS:左边的表达式包含右边的表达式。 ENDSWITH:左边的表达式以右边的表达式作为结束。 LIKE:左边的表达式等于右边的表达式:?和*可作为通配符,其中?匹配1个字符,*匹配0个或者多个字符。 MATCHES:左边的表达式根据ICU v3的regex风格比较,等于右边的表达式。 可参考以下代码: 1 2 3 4 5 6 NSString *regex = @ "[A-Za-z]+" ; NSPredicate *matchpredicate = [ NSPredicate predicateWithFormat:@ "SELF MATCHES %@" , regex]; if ([matchpredicate evaluateWithObject:@ "keso" ]) { NSLog (@ "匹配成功" ); } 关系操作 ANY,SOME:指定下列表达式中的任意元素。比如,ANY children.age < 18。 ALL:指定下列表达式中的所有元素。比如,ALL children.age < 18。 NONE:指定下列表达式中没有的元素。比如,NONE children.age < 18。它在逻辑上等于NOT (ANY ...)。 IN:等于SQL的IN操作,左边的表达必须出现在右边指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' }。 数组操作 array[index]:指定数组中特定索引处的元素。 array[FIRST]:指定数组中的第一个元素。 array[LAST]:指定数组中的最后一个元素。 array[SIZE]:指定数组的大小。 布尔值谓词 TRUEPREDICATE:结果始终为真的谓词。 FALSEPREDICATE:结果始终为假的谓词。 下面提供一个简单使用谓词搜索类对象的代码: 新建一个People类,头文件: 1 2 3 4 5 6 7 8 9 10 11 @interface People : NSObject @property (strong, nonatomic ) NSString *FirstName; @property (strong, nonatomic ) NSString *LastName; @property ( nonatomic ) NSInteger Height; - ( NSString *)description; @end People.m文件: 1 2 3 4 5 6 7 @implementation People - ( NSString *)description { return [ NSString stringWithFormat:@ "%@%@" , self .LastName, self .FirstName]; }; @end 具体实现代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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实现,比如一下代码是等价的: 1 2 3 NSCompoundPredicate *comPredicate=[ NSCompoundPredicate andPredicateWithSubpredicates:@[[ NSPredicate predicateWithFormat:@ "Height > 90" ], [ NSPredicate predicateWithFormat:@ "FirstName = %@" , @ "介石" ]]]; NSPredicate *secondPredicate=[ NSPredicate predicateWithFormat:@ "(Height > 90) AND (FirstName = %@)" , @ "介石" ]; NSComparisonPredicate有两个调用的静态方法: 1 2 + ( 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类型: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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) }; 本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4264869.html,如需转载请自行联系原作者