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 },或者INPUT BETWEEN {INPUT BETWEEN {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,如需转载请自行联系原作者

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值