尝试评估NSExpression或NSPredcate时使用SIGABRT



我正在尝试将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:

  1. 在NSExpression或NSPredcate上使用受保护的变量名(例如size((应改用mySize(。

    (在我的NSExpression示例中,它成功了,因为我使用了变量名myVar,如果我尝试将变量更改为size,它会产生相同的SIGABRT

  2. 尝试将myVarNSPredicate.withSubstitutionVariables(:)一起使用(应该使用$myVar(。

  3. 尝试将$myVarNSPredicate.evaluate(with:)一起使用(应该使用myVar(。

  4. 尝试将$myVarNSExpression.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"]

您需要进行不区分大小写的比较。

最新更新