Cocoa中谓词(Predicate)提供了一个通用的查询方式处理数据,可以获取和指定数据的过滤形式,Cocoa实际开发中可以是使用NSPredicate及其父类NSComparisonPredicate和NSCompoundPredicate.其风格类似于SQL查询语言和正则表达式的混合体,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。一般来说稍微操作过数据库基本上很容易理解其中的方法,至于使用的方法也很简单。
集合中的NSPredicate
首先来一段比较简单的代码:
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)评估,而集合则是内存中过滤。这时候我们有必要里了解一下基本比较运算符:
- =, ==:左边的表达式和右边的表达式相等。
- >=, =>:左边的表达式大于或者等于右边的表达式。
- <=, =<:左边的表达式小于等于右边的表达式。
- >:左边的表达式大于右边的表达式。
- <:左边的表达式小于右边的表达式。
- !=, <>:左边的表达式不等于右边的表达式。
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:结果始终为假的谓词。
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,如需转载请自行联系原作者