我正在尝试将NSExpression+NSPredcate组合起来,以创建一个简单的功能,用户将键入类似size + 1 > 3
的内容,并对表达式进行求值。
首先,为了确保NSExpression能够与变量一起工作,我尝试了以下操作:
NSExpression(format: "2 + 1")
.expressionValue(with: nil, context: nil)
// == 3
NSExpression(format: "myInt + 1")
.expressionValue(with: ["myInt": 2], context: nil)
// == 3
接下来,为了确保我可以评估NSPredcate,我尝试了以下操作:
NSPredicate(format: "2 + 1 == 3")
.evaluate(with: nil)
// == true
现在,当我尝试将两者组合时,无论我尝试哪种组合,我都会得到error: Execution was interrupted, reason: signal SIGABRT.
:
NSPredicate(format: "size + 1 == 3")
.evaluate(with: ["size": 2])
// error: Execution was interrupted, reason: signal SIGABRT.
NSPredicate(format: "$size + 1 == 3")
.evaluate(with: ["size": 2])
// error: Execution was interrupted, reason: signal SIGABRT.
NSPredicate(format: "size + 1 == 3")
.withSubstitutionVariables(["size": 2])
.evaluate(with: nil)
// error: Execution was interrupted, reason: signal SIGABRT.
NSPredicate(format: "$size + 1 == 3")
.withSubstitutionVariables(["size": 2])
.evaluate(with: nil)
// error: Execution was interrupted, reason: signal SIGABRT.
我知道大多数NSPredcate都用于过滤列表,这让我怀疑像上面这样的用例是否可行。
是否可以在NSPredcate中使用一次性评估的变量?
上面的代码中有几件事可以导致SIGABRT
:
-
在NSExpression或NSPredcate上使用受保护的变量名(例如
size
((应改用mySize
(。(在我的NSExpression示例中,它成功了,因为我使用了变量名
myVar
,如果我尝试将变量更改为size
,它会产生相同的SIGABRT
。 -
尝试将
myVar
与NSPredicate.withSubstitutionVariables(:)
一起使用(应该使用$myVar
(。 -
尝试将
$myVar
与NSPredicate.evaluate(with:)
一起使用(应该使用myVar
(。 -
尝试将
$myVar
与NSExpression.evaluate(with:context:)
一起使用(应该使用myVar
(。
这两种方法都有效:
NSPredicate(format: "mySize + 1 == 3")
.evaluate(with: ["mySize": 2])
// == true
NSPredicate(format: "$mySize + 1 == 3")
.withSubstitutionVariables(["mySize": 2])
.evaluate(with: nil)
// == true
您甚至可以在两者中定义相同的变量:
NSPredicate(format: "mySize == $mySize")
.withSubstitutionVariables(["mySize": 2])
.evaluate(with: ["mySize": 2])
// == true
然而,你可能只想坚持其中一个。
更新:为了避免保留关键字,您可以将提供的词典与Martin链接到的以下列表进行比较:
/// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html
let reservedKeywords = ["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", "FETCH", "CAST", "TRUEPREDICATE", "FALSEPREDICATE", "UTI-CONFORMS-TO", "UTI-EQUALS"]
您需要进行不区分大小写的比较。