谓词编程指南(摘要)
前端之家收集整理的这篇文章主要介绍了
谓词编程指南(摘要),
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
- 谓词概览
- 创建谓词
- 使用格式化字符串创建谓词
- 字符串常量、变量及通配符
- 布尔值
- 动态属性名
- 在代码中创建谓词
- 使用谓词模板创建谓词
- 格式化字符串总结
- 使用谓词
- 对谓词进行评估
- 谓词与数组结合
- 在谓词中使用键路径
- Null值
- 性能
- 谓词格式化字符串语法
- 分析器基本要素
- 基本比较
- 布尔值谓词
- 基本复合谓词
- 字符串比较
- 集合操作
- 标识符
- 字面量
- 保留字
在Cocoa中,谓词提供了指定查询的一个通用手段。谓词系统在多个领域都是能干的,包括Core Data及Spotlight。谓词是一个逻辑操作符,只返回布尔值。
两类谓词:
- 比较谓词:使用一个操作符比较两个表达式。
- 复合谓词:比较两个或更多谓词的结果,或否定其它谓词。
谓词的类型比较广泛,包括:
- 简单比较,如grade == 7或firstName like ‘Mark’
- 不区分大小写或字符的查找,如name contains[cd] ‘citroen’
- 逻辑操作,如(firstName begins with ‘M’) AND (lastName like ‘Adderley’)
与谓词相关的类:NSPredicate、NSComparisonPredicate、NSCompoundPredicate。
谓词表达式是用NSExpression表示的。
谓词的局限性:
不提供并集、交集功能。谓词能不能正常工作,与操作符相关,也与后台存储相关,例如:
matches操作符使用了regex,尽管它可以在内存过滤中工作,但不被Core Data的sql存储所支持。
Core Data的sql存储的每次查询只支持一对多操作,此时,谓词中只能使用ALL、ANY、IN三个操作符中的一个。
创建谓词
使用格式化字符串创建谓词
使用NSPredicate的类方法predicateWithFormat:创建谓词。
|
NSPredicate
*predicate
=
[
NSPredicate
predicateWithFormat
:
@"(lastName like[cd] %@) AND (birthday > %@)"
,
lastNameSearchString
birthdaySearchDate
]
;
|
在这个示例中,[cd]表示大小写及发音符号不敏感。
谓词字符串分析器对空白不敏感,对关键字大小写不敏感,支持嵌套的括号表达式。也支持格式化参数,例如%x、%@。在谓词中,可以使用$指示一个变量,例如$VAR_NAME。分析器不会进行语法检查。
字符串常量、变量及通配符
字符串常量必须使用引号,单引号、双引号均可,但单引号不能匹配双引号。使用变量置换时,例如firstName like %@,此时,引号会被自动添加进去。如果在格式化字符串中使用了字符串常量,就必须自己对其添加引号。
|
NSPredicate
*predicate
=
[
NSPredicate
predicateWithFormat
:
@"lastName like[c] \"S*\""
]
;
|
使用通配符时,要先将通配符添加到变量中,然后再进行置换。
NSString
*prefix
@"prefix"
;
*suffix
@"suffix"
;
@"SELF like[c] %@"
[
[
prefix
stringByAppendingString
@"*"
]
stringByAppendingString
:suffix
;
BOOL
ok
predicate
evaluateWithObject
@"prefixxxxxxsuffix"
;
|
上面的示例,得到的谓词字符串是SELF LIKE[c] “prefix*suffix”,ok的值是YES。
但如果是这样写:
predicate
@"SELF like[c] %@*%@"
,
prefix
suffix
;
ok
[
predicate
evaluateWithObject
@"prefixxxxxxsuffix"
;
|
得到的谓词字符串将会是SELF LIKE[c] “prefix”*”suffix”,这明显是错误的!
同样,应该注意,格式化字符串中变量置换与变量表达式中变量置换的差别。
布尔值
*newPredicate
@"anAttribute == %@"
NSNumber
numberWithBool
:aBool
;
*testForTrue
@"anAttribute == YES"
;
|
当字符串变量对格式化字符串中的格式化参数进行置换时,字符串变量会自动添加引号,所以,不能使用%@指定动态属性名。这个示例就是错误的:
2
3
NSString
*attributeName
@"firstName"
;
*attributeValue
@"Adam"
;
@"%@ like %@"
attributeName
attributeValue
;
|
因为得到的谓词字符串是”firstName” like “Adam”。
正确的做法是在格式化字符串中使用%K指定动态属性名。下面的示例才是正确的:
predicate
@"%K like %@"
attributeName
attributeValue
;
|
这里得到的谓词字符串是firstName like “Adam”。
在代码中创建谓词
创建一个表示(revenue >= 1000000) and (revenue < 100000000)的谓词:
2
3
4
5
6
7
8
9
NSExpression
*lhs
NSExpression
expressionForKeyPath
@"revenue"
;
*greaterThanRhs
expressionForConstantValue
:
NSNumber
numberWithInt
:
1000000
;
*greaterThanPredicate
NSComparisonPredicate
predicateWithLeftExpression
:lhs
rightExpression
:greaterThanRhs
modifier
:NSDirectPredicateModifier
type
:NSGreaterThanOrEqualToPredicateOperatorType
options
0
;
*lessThanRhs
100000000
;
*lessThanPredicate
:lessThanRhs
:NSLessThanPredicateOperatorType
;
NSCompoundPredicate
NSCompoundPredicate
andPredicateWithSubpredicates
@
greaterThanPredicate
lessThanPredicate
;
|
这种方式的缺点就是需要编写大量代码。优点是不易拼写错误,速度比那些依赖字符串解析的谓词快。
使用谓词模板创建谓词
谓词模板在格式化字符串及纯代码之间提供了折衷方案。谓词模板就是包含了一个变量表达式的谓词。
*predicateTemplate
@"lastName like[c] $LAST_NAME"
;
predicateTemplate
predicateWithSubstitutionVariables
:
NSDictionary
dictionaryWithObject
@"Turner"
forKey
@"LAST_NAME"
;
|
上面的示例得到的谓词是lastName LIKE[c] “Turner”。
置换字典中的键值对必须包含谓词所指定的所有变量。当匹配null值时,必须使用[NSNull null]。
2
@"date = $DATE"
;
predicateWithSubstitutionVariables
NSDictionary
dictionaryWithObject
NSNull
null
]
forKey
@"DATE"
;
|
上面的示例得到的谓词是date == <null>。
格式化字符串总结
@”attributeName == %@”
@”%K == %@”
@”name IN $NAME_LIST”
@”‘name’ IN $NAME_LIST”
@”$name IN $NAME_LIST”
@”%K == ‘%@'”
使用谓词
对谓词进行评估
使用evaluateWithObject:方法。
@"SELF IN %@"
@
[
@"Stig"
@"Shaffiq"
@"Chris"
;
result
;
|
谓词与数组结合
NSArray提供了filteredArrayUsingPredicate:方法,NSMutableArray提供了filterUsingPredicate:方法。
在谓词中使用键路径
@"department.name like %@"
departmentName
;
|
Null值
在谓词中,只有nil及[NSNull null]与null值相等。
谓词与Core Data结合
正则表达式
比较下面两段代码
@"( title matches .*mar[1-10] ) OR ( type = 1 )"
;
|
@"( type = 1 ) OR ( title matches .*mar[1-10] )"
;
|
第二段代码的性能更好一些。
Join
join(子查询)性能也很差,要尽量避免使用它。当测试对一关系时,测试对象相等比测试对象的属性更高效。
@"department == %@"
department
;
|
第一段代码比第二段代码更高效。
谓词格式化字符串语法
分析器基本要素
$用于指示一个变量。
%@用于置换一个对象,通常是字符串、数值、日期。
%K用于置换一个键路径。
基本比较
=与==:左表达式等于右表达式
>=与=>:左表达式大于或等于右表达式
<=与=<:左表达式小于或等于右表达式
>:左表达式大于右表达式
<:左表达式小于右表达式
!=与<>:左表达式不等于右表达式
BETWEEN:左表达式是右表达式中的某个值
布尔值谓词
TRUEPREDICATE:这个谓词的评估结果总是TRUE
FALSEPREDICATE:这个谓词的评估结果总是FALSE
基本复合谓词
AND与&&:逻辑与
OR与||:逻辑或
NOT与!:逻辑非
字符串比较
BEGINSWITH:左表达式以右表达式开始
CONTAINS:左表达式包含右表达式
ENDSWITH:左表达式以右表达式结束
LIKE:左表达式等于右表达式,可以使用?及*通配符,?匹配一个字符,*匹配0个或多个字符。
MATCHES:左表达式等于右表达式,这里使用的是正则表达式比较。
集合操作
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中指定索引处的元素。
array[FIRST]:指定某个数组array中第一个索引处的元素。
array[LAST]:指定某个数组array中最后一个索引处的元素。
array[SIZE]:指定某个数组array中元素的个数。
标识符
C样式标识符不是保留字。
#symbol:将保留字转换为用户标识符。
[\]{octaldigit}{3}:用于转换八进制数(\后跟随3个八进制数字)
[\][xX]{hexdigit}{2}:用于转换十六进制数(\x或\X后跟随2个十六进制数字)
[\][uU]{hexdigit}{4}:用于转换Unicode数(\u或\U后跟随4个十六进制数字)
字面量
FALSE与NO:逻辑假
TRUE与YES:逻辑真
NULL与NIL:null值
SELF:代表被评估的对象
“text”:字符串
‘text’:字符串
逗号分割的字面数组:例如,{ ‘comma’,‘separated’,‘literal’,‘array’ }
标准整数与点计数法:27、3.14
取幂的点计数法:9.2e-5
0x:十六进制数字序列
0o:八进制数字序列
0b:二进制数字序列
保留字
AND,OR,IN,NOT,ALL,ANY,SOME,NONE,LIKE,CASEINSENSITIVE,CI,MATCHES,CONTAINS,BEGINSWITH,ENDSWITH,BETWEEN,NULL,NIL,SELF,TRUE,YES,FALSE,NO,FIRST,LAST,SIZE,ANYKEY,SUBQUERY,CAST,TRUEPREDICATE,FALSEPREDICATE