【问题标题】:SIGABRT when trying to evaluate an NSExpression or NSPredicate尝试评估 NSExpression 或 NSPredicate 时的 SIGABRT
【发布时间】:2023-03-28 22:18:01
【问题描述】:

我正在尝试组合 NSExpression + NSPredicate 来创建一个简单的功能,用户可以在其中输入类似 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

接下来,为了确保我可以评估 NSPredicate,我尝试了以下方法:

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.

我知道大多数 NSPredicate 用于过滤列表,这让我想知道像上面这样的用例是否可以工作。

是否可以在 NSPredicate 中使用一次性评估的变量?

【问题讨论】:

    标签: swift nspredicate nsexpression


    【解决方案1】:

    上面的代码中有几处可以导致SIGABRT

    1. 在 NSExpression 或 NSPredicate 上使用受保护的变量名(例如 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"]
    

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

    【讨论】:

    • 保留字列在本页末尾:Predicate Format String Syntax。它们不区分大小写。
    • 一种安全的方法是使用密钥路径替换,例如NSPredicate(format: "%K + 1 == 3", "size").
    • 好点!但是,用户提供了完整的表达式,所以我不能使用%K。例如。他们正在输入整个字符串:mySize + 1 == 3.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 2013-08-06
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多