There are three ways to create a predicate in Cocoa: using a format string, directly in code, and from a predicate template.
- 在Cocoa中有三种创建谓词的方法:使用格式字符串,直接在代码中,以及从谓词模板中使用。
Creating a Predicate Using a Format String
You can use NSPredicate class methods of the form predicateWithFormat… to create a predicate directly from a string. You define the predicate as a string, optionally using variable substitution. At runtime, variable substitution—if any—is performed, and the resulting string is parsed to create corresponding predicate and expression objects. The following example creates a compound predicate with two comparison predicates.
- 您可以使用形式predicateWithFormat ...的NSPredicate类方法直接从字符串创建谓词。 您可以将谓词定义为字符串,也可以使用变量替换。 在运行时,执行变量替换(如果有),并解析生成的字符串以创建相应的谓词和表达式对象。 以下示例使用两个比较谓词创建复合谓词。
NSPredicate *predicate = [NSPredicate
predicateWithFormat:@"(lastName like[cd] %@) AND (birthday > %@)",
lastNameSearchString, birthdaySearchDate];
(In the example, like[cd]
is a modified “like” operator that is case-insensitive and diacritic-insensitive.) For a complete description of the string syntax and a list of all the operators available, see Predicate Format String Syntax.
-(在示例中,like[cd]是一个不区分大小写且对变音不敏感的修改后的“like”运算符。)有关字符串语法的完整说明以及所有可用运算符的列表,请参阅谓词格式字符串语法。
Important: The predicate format string syntax is different from the regular expression syntax. The regular expression syntax is defined by the ICU—see http://www.icu-project.org/userguide/regexp.html.
- 要点:谓词格式字符串语法与正则表达式语法不同。 正则表达式语法由ICU定义 - 请参阅http://www.icu-project.org/userguide/regexp.html。
The predicate string parser is whitespace insensitive, case insensitive with respect to keywords, and supports nested parenthetical expressions. It also supports printf
-style format specifiers (like %x
and %@
)—see Formatting String Objects. Variables are denoted with a $
(for example $VARIABLE_NAME
)—see Creating Predicates Using Predicate Templates for more details.
- 谓词字符串解析器对空格不敏感,对关键字不区分大小写,并支持嵌套的括号表达式。 它还支持printf样式的格式说明符(如%x和%@) - 请参阅格式化字符串对象。变量用
$
表示(例如$ VARIABLE_NAME) - 请参阅使用谓词模板创建谓词以获取更多详细信息。
The parser does not perform any semantic type checking. It makes a best-guess effort to create suitable expressions, but—particularly in the case of substitution variables—it is possible that a runtime error will be generated.
- 解析器不执行任何语义类型检查。 它可以最大限度地尝试创建合适的表达式,但是 - 特别是在替换变量的情况下 - 可能会生成运行时错误。
This approach is typically best used for predefined query terms, although variable substitution allows for considerable flexibility. The disadvantage of this technique is that you must take care to avoid introducing errors into the string—you will not discover mistakes until runtime.
- 这种方法通常最适用于预定义的查询术语,尽管变量替换允许相当大的灵活性。 这种技术的缺点是你必须注意避免在字符串中引入错误 - 在运行之前你不会发现错误。
String Constants, Variables, and Wildcards
- 字符串常量,变量和通配符
String constants must be quoted within the expression—single and double quotes are both acceptable, but must be paired appropriately (that is, a double quote (") does not match a single quote (')). If you use variable substitution using %@ (such as firstName like %@), the quotation marks are added for you automatically. If you use string constants within your format string, you must quote them yourself, as in the following example.
- 字符串常量必须在表达式中引用 - 单引号和双引号都是可接受的,但必须适当配对(即双引号(“)与单引号(')不匹配。)如果使用变量替换请使用%@(例如firstName,如%@),引号会自动添加。如果在格式字符串中使用字符串常量,则必须自己引用它们,如下例所示。
NSPredicate *predicate = [NSPredicate
predicateWithFormat:@"lastName like[c] \"S*\""];
You must take automatic quotation into account when using wildcards—you must add wildcards to a variable prior to substitution, as shown in the following example.
- 使用通配符时必须考虑自动引用 - 必须在替换之前将通配符添加到变量,如以下示例所示。
NSString *prefix = @"prefix";
NSString *suffix = @"suffix";
NSPredicate *predicate = [NSPredicate
predicateWithFormat:@"SELF like[c] %@",
[[prefix stringByAppendingString:@"*"] stringByAppendingString:suffix]];
BOOL ok = [predicate evaluateWithObject:@"prefixxxxxxsuffix"];
In this example, variable substitution produces the predicate string SELF LIKE[c] "prefix*suffix", and the value of ok is YES. The following fragment, by contrast, yields the predicate string SELF LIKE[c] "prefix" * "suffix", and the predicate evaluation yields a runtime error:
- 在此示例中,变量替换生成谓词字符串SELF LIKE [c]“prefix * suffix”,ok的值为YES。 相反,以下片段产生谓词字符串SELF LIKE [c]“prefix”*“suffix”,谓词评估产生运行时错误:
predicate = [NSPredicate
predicateWithFormat:@"SELF like[c] %@*%@", prefix, suffix];
ok = [predicate evaluateWithObject:@"prefixxxxxxsuffix"];
Finally, the following fragment results in a runtime parse error (Unable to parse the format string "SELF like[c] %@*").
- 最后,以下片段导致运行时解析错误(无法解析格式字符串“SELF like [c]%@ *”)。
predicate = [NSPredicate
predicateWithFormat:@"SELF like[c] %@*", prefix];
You should also note the difference between variable substitution in the format string and variable expressions. The following code fragment creates a predicate with a right-hand side that is a variable expression.
- 您还应该注意格式字符串和变量表达式中的变量替换之间的区别。 以下代码片段创建一个谓词,其右侧是变量表达式。
predicate = [NSPredicate
predicateWithFormat:@"lastName like[c] $LAST_NAME"];
For more about variable expressions, see Creating Predicates Using Predicate Templates.
- 有关变量表达式的更多信息,请参阅使用谓词模板创建谓词。
Boolean Values
You specify and test for equality of Boolean values as illustrated in the following examples:
- 您可以指定并测试布尔值的相等性,如以下示例所示:
NSPredicate *newPredicate =
[NSPredicate predicateWithFormat:@"anAttribute == %@",
[NSNumber numberWithBool:aBool]];
NSPredicate *testForTrue =
[NSPredicate predicateWithFormat:@"anAttribute == YES"];
Dynamic Property Names
Because string variables are surrounded by quotation marks when they are substituted into a format string using %@, you cannot use %@ to specify a dynamic property name—as illustrated in the following example.
- 因为字符串变量在使用%@替换为格式字符串时会被引号括起来,所以不能使用%@来指定动态属性名称 - 如以下示例所示。
NSString *attributeName = @"firstName";
NSString *attributeValue = @"Adam";
NSPredicate *predicate =
[NSPredicate predicateWithFormat:@"%@ like %@",
attributeName, attributeValue];
The predicate format string in this case evaluates to "firstName" like "Adam".
- 在这种情况下,谓词格式字符串的计算结果为“firstName”,like “Adam”。
If you want to specify a dynamic property name, you use %K in the format string, as shown in the following fragment.
- 如果要指定动态属性名称,请在格式字符串中使用%K,如以下片段所示。
predicate = [NSPredicate predicateWithFormat:@"%K like %@",
attributeName, attributeValue];
The predicate format string in this case evaluates to firstName like "Adam"
(note that there are no quotation marks around firstName
).
- 在这种情况下,谓词格式字符串的计算结果为firstName,like “Adam”(请注意firstName周围没有引号)。
Creating Predicates Directly in Code
You can create predicate and expression instances directly in code. NSComparisonPredicate and NSCompoundPredicate provide convenience methods that allow you to easily create compound and comparison predicates respectively. NSComparisonPredicate provides a number of operators ranging from simple equality tests to custom functions.
- 您可以直接在代码中创建谓词和表达式实例。 NSComparisonPredicate和NSCompoundPredicate提供了方便的方法,使您可以分别轻松创建复合谓词和比较谓词。 NSComparisonPredicate提供了许多运算符,从简单的相等性测试到自定义函数。
The following example shows how to create a predicate to represent (revenue >= 1000000) and (revenue < 100000000). Note that the same left-hand side expression is used for both comparison predicates.
- 以下示例显示如何创建谓词以表示(收入> = 1000000)和(收入<100000000)。 请注意,两个比较谓词都使用相同的左侧表达式。
NSExpression *lhs = [NSExpression expressionForKeyPath:@"revenue"];
NSExpression *greaterThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:1000000]];
NSPredicate *greaterThanPredicate = [NSComparisonPredicate
predicateWithLeftExpression:lhs
rightExpression:greaterThanRhs
modifier:NSDirectPredicateModifier
type:NSGreaterThanOrEqualToPredicateOperatorType
options:0];
NSExpression *lessThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:100000000]];
NSPredicate *lessThanPredicate = [NSComparisonPredicate
predicateWithLeftExpression:lhs
rightExpression:lessThanRhs
modifier:NSDirectPredicateModifier
type:NSLessThanPredicateOperatorType
options:0];
NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
@[greaterThanPredicate, lessThanPredicate]];
The disadvantage of this technique should be immediately apparent—you may have to write a lot of code. The advantages are that it is less prone to spelling and other typographical errors that may only be discovered at runtime and it may be faster than depending on string parsing.
- 这种技术的缺点应该是显而易见的 - 您可能需要编写大量代码。 优点是它不易于拼写和其他印刷错误,这些错误只能在运行时发现,而且可能比依赖字符串解析更快。
This technique is most likely to be useful when the creation of the predicate is itself dynamic, such as in a predicate builder.
- 当谓词的创建本身是动态的时,这种技术最有用,例如在谓词构建器中。
Creating Predicates Using Predicate Templates
Predicate templates offer a good compromise between the easy-to-use but potentially error-prone format string-based technique and the code-intensive pure coding approach. A predicate template is simply a predicate that includes a variable expression. (If you are using the Core Data framework, you can use the Xcode design tools to add predicate templates for fetch requests to your model—see Managed Object Models.) The following example uses a format string to create a predicate with a right-hand side that is a variable expression.
- 谓词模板在易于使用但可能容易出错的基于字符串的格式技术与代码密集型纯编码方法之间提供了良好的折衷。 谓词模板只是一个包含变量表达式的谓词。 (如果您使用的是Core Data框架,则可以使用Xcode设计工具为模型添加获取请求的谓词模板 - 请参阅托管对象模型。)以下示例使用格式字符串创建带右侧的谓词 这是一个变量表达式。
NSPredicate *predicateTemplate = [NSPredicate
predicateWithFormat:@"lastName like[c] $LAST_NAME"];
This is equivalent to creating the variable expression directly as shown in the following example.
- 这相当于直接创建变量表达式,如以下示例所示。
NSExpression *lhs = [NSExpression expressionForKeyPath:@"lastName"];
NSExpression *rhs = [NSExpression expressionForVariable:@"LAST_NAME"];
NSPredicate *predicateTemplate = [NSComparisonPredicate
predicateWithLeftExpression:lhs
rightExpression:rhs
modifier:NSDirectPredicateModifier
type:NSLikePredicateOperatorType
options:NSCaseInsensitivePredicateOption];
To create a valid predicate to evaluate against an object, you use the NSPredicate method predicateWithSubstitutionVariables: to pass in a dictionary that contains the variables to be substituted. (Note that the dictionary must contain key-value pairs for all the variables specified in the predicate.)
- 要创建有效的谓词来评估对象,可以使用NSPredicate方法predicateWithSubstitutionVariables:传入包含要替换的变量的字典。 (请注意,字典必须包含谓词中指定的所有变量的键值对。)
NSPredicate *predicate = [predicateTemplate predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObject:@"Turner" forKey:@"LAST_NAME"]];
The new predicate returned by this example is lastName LIKE[c] "Turner".
- 此示例返回的新谓词是lastName LIKE [c]“Turner”。
Because the substitution dictionary must contain key-value pairs for all the variables specified in the predicate, if you want to match a null value, you must provide a null value in the dictionary, as illustrated in the following example.
- 因为替换字典必须包含谓词中指定的所有变量的键值对,所以如果要匹配空值,则必须在字典中提供空值,如以下示例所示。
NSPredicate *predicate = [NSPredicate
predicateWithFormat:@"date = $DATE"];
predicate = [predicate predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObject:[NSNull null] forKey:@"DATE"]];
The predicate formed by this example is date == <null>
.
- 这个例子形成的谓词是
date == <null>
。
Format String Summary
It is important to distinguish between the different types of value in a format string. Note also that single or double quoting variables (or substitution variable strings) will cause %@, %K, or $variable to be interpreted as a literal in the format string and so will prevent any substitution.
- 区分格式字符串中的不同类型的值很重要。 另请注意,单引号或双引号变量(或替换变量字符串)将导致%@,%K或$变量被解释为格式字符串中的文字,因此将阻止任何替换。
@"attributeName == %@"
This predicate checks whether the value of the key attributeName is the same as the value of the object %@ that is supplied at runtime as an argument to predicateWithFormat:. Note that %@ can be a placeholder for any object whose description is valid in the predicate, such as an instance of NSDate, NSNumber, NSDecimalNumber, or NSString.
- 此谓词检查键attributeName的值是否与在运行时作为predicateWithFormat:的参数提供的对象%@的值相同。 请注意,%@可以是谓词中描述有效的任何对象的占位符,例如NSDate,NSNumber,NSDecimalNumber或NSString的实例。
@"%K == %@"
This predicate checks whether the value of the key %K is the same as the value of the object %@. The variables are supplied at runtime as arguments to predicateWithFormat:.
- 该谓词检查键%K的值是否与对象%@的值相同。 变量在运行时作为predicateWithFormat的参数提供。
@"name IN $
NAME_LIST"
This is a template for a predicate that checks whether the value of the key name is in the variable $NAME_LIST (no quotes) that is supplied at runtime using predicateWithSubstitutionVariables:.
- 这是谓词的模板,用于检查键名的值是否在运行时使用predicateWithSubstitutionVariables:提供的变量$ NAME_LIST(无引号)中。
@"'name' IN $
NAME_LIST"
This is a template for a predicate that checks whether the constant value 'name' (note the quotes around the string) is in the variable $NAME_LIST that is supplied at runtime using predicateWithSubstitutionVariables:.
- 这是一个谓词模板,用于检查常量值'name'(注意字符串周围的引号)是否在运行时使用predicateWithSubstitutionVariables:提供的变量$ NAME_LIST中。
@"$
name IN $
NAME_LIST"
This is a template for a predicate that expects values to be substituted (using predicateWithSubstitutionVariables:) for both $
NAME and $
NAME_LIST.
- 这是一个谓词模板,它希望为 NAME_LIST替换值(使用predicateWithSubstitutionVariables :)。
@"%K == '%@'"
This predicate checks whether the value of the key %K is equal to the string literal “%@“ (note the single quotes around %@). The key name %K is supplied at runtime as an argument to predicateWithFormat:.
- 该谓词检查键%K的值是否等于字符串文字“%@”(注意%@周围的单引号)。 密钥名称%K在运行时作为predicateWithFormat:的参数提供。
网友评论