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,
NSLessThanOrEqualToPredicateOperatorType
,
NSGreaterThanPredicateOperatorType
,
NSGreaterThanOrEqualToPredicateOperatorType
,
NSEqualToPredicateOperatorType
,
NSNotEqualToPredicateOperatorType
,
NSMatchesPredicateOperatorType
,
NSLikePredicateOperatorType
,
NSBeginsWithPredicateOperatorType
,
NSEndsWithPredicateOperatorType
,
NSInPredicateOperatorType
,
NSCustomSelectorPredicateOperatorType
,
NSContainsPredicateOperatorType
NS_ENUM_AVAILABLE
(10_5, 3_0) = 99,
NSBetweenPredicateOperatorType
NS_ENUM_AVAILABLE
(10_5, 3_0)
};
|
本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4264869.html,如需转载请自行联系原作者