博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS开发-NSPredicate
阅读量:6157 次
发布时间:2019-06-21

本文共 6586 字,大约阅读时间需要 21 分钟。

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

你可能感兴趣的文章
Ajax异步
查看>>
好记性不如烂笔杆-android学习笔记<十六> switcher和gallery
查看>>
JAVA GC
查看>>
3springboot:springboot配置文件(外部配置加载顺序、自动配置原理,@Conditional)
查看>>
图解SSH原理及两种登录方法
查看>>
【总结整理】JQuery基础学习---样式篇
查看>>
查询个人站点的文章、分类和标签查询
查看>>
基础知识:数字、字符串、列表 的类型及内置方法
查看>>
JSP的隐式对象
查看>>
JS图片跟着鼠标跑效果
查看>>
[SCOI2005][BZOJ 1084]最大子矩阵
查看>>
学习笔记之Data Visualization
查看>>
Leetcode 3. Longest Substring Without Repeating Characters
查看>>
416. Partition Equal Subset Sum
查看>>
app内部H5测试点总结
查看>>
[TC13761]Mutalisk
查看>>
while()
查看>>
常用限制input的方法
查看>>
IIS7下使用urlrewriter.dll配置
查看>>
并行程序设计学习心得1——并行计算机存储
查看>>