【问题标题】:NSPredicate not replacing %@ parameter - Swift 4NSPredicate 不替换 %@ 参数 - Swift 4
【发布时间】:2018-06-05 14:28:33
【问题描述】:

我正在尝试使用谓词:

let predicate = NSPredicate(format: "organizationName == '%@'", orgName)

它没有返回任何结果,所以我记录了predicate.predicateFormat 以确保谓词中包含正确的值。它显示:

predicateForEnablingContact: organizationName == "%@"

如您所见,%@ 可替换参数没有被替换。

如果我在谓词中硬编码一个实际值,以进行测试,谓词可以正常工作。

我所能找到的似乎与我的问题有很大关系的是这个 SO 问题:iOS 11 NSPredicate search on Swift array crashing - NSUnknownKeyException。该解决方案表明谓词可能与@objc 推理更改存在一些问题。

不过,我没有看到其他很多人遇到这个问题。最近有一些带有选定答案的谓词相关问题,例如这个问题,它显示使用可替换参数:Swift: 'IN' query alternative using NSPredicate for fetching records from iCloud

我只是错过了一些简单的东西吗???


我的代码,以防它带来任何其他想法:

let contactPicker = CNContactPickerViewController()
contactPicker.delegate = self;

contactPicker.displayedPropertyKeys = [CNContactPhoneNumbersKey]

let predicate = NSPredicate(format: "organizationName == '%@'", orgName)

os_log("orgName = %{public}@\tpredicateForEnablingContact: %{public}@", log: debugLog, type: .debug, title, predicate.predicateFormat)

contactPicker.predicateForEnablingContact = predicate
present(contactPicker, animated: true, completion: nil)

联系人选择器出现;但是没有选择任何项目 - 再次,除非我将 orgName 值硬编码到谓词中。然后,启用正确的联系人。

更新:
如果我删除引号,我会收到带有以下消息的 signal SIGABRT

2017-12-23 12:35:56.871282-0600 MyApp[1337:1170156] * 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无法解析格式字符串“organizationName == %@ "'
*
首先抛出调用栈: (0x1827d5d04 0x181a24528 0x1830e6fdc 0x1830e577c 0x101325144 0x101297ee0 0x1006a6724 0x1006a6cb4 0x18bd251c8 0x18bdce390 0x18be7cf68 0x18be7030c 0x18bbffabc 0x18277d848 0x18277b200 0x18277b7bc 0x18269bfb8 0x184533f84 0x18bc702e8 0x1006af6fc 0x1821be56c),点击 libc++abi.dylib:以 NSException 类型的未捕获异常终止

是的,我确实设置了异常断点 - 没有提供有关该问题的其他信息。正如我在评论中指出的,异常中断发生在let predicate = NSPredicate(format: "organizationName == %@", orgName) 行。

那个中断是我添加引号的原因 - 如果我有引号,它不会中断;它只是不返回任何结果。同样,记录谓词会显示“无法解析...”消息中指示的相同字符串(在这种情况下包括引号除外)。

我还尝试将== 替换为CONTAINS[c]MATCHES[c],结果相同。当然,无论如何它都应该适用于==

更新 2:
FWIW,我使用的是 Xcode 版本 9.2 (9C40b)

Swift --version 显示:

Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)
Target: x86_64-apple-macosx10.9

更新 3: 将此放在问题中,以防我的评论消失:
啊……我不知道到底发生了什么,但我想我在orgName 中有一个NSPredicate 不喜欢的角色。我删除并重新输入(确切地说?)我将值分配给orgName 的代码 - 现在它在没有引号的情况下工作。我投票赞成当前的答案,因为响应者花时间考虑我的问题 - 并为这个问题的访问者提出了很好的观点。

【问题讨论】:

  • 尝试删除引号。正如Predicate Programming Guide 所说,“单引号或双引号变量(或替换变量字符串)会导致 %@、%K 或 $variable 在格式字符串中被解释为文字,从而防止任何替换。”
  • 当我删除引号时,我得到一个异常。所有异常都说这是一个未捕获的异常——而不是我链接的问题中的键值消息。根本没有细节。我会在早上发布确切的消息。它在let predicate = 行中断。
  • 啊……我不知道到底发生了什么,但我想我在orgName 中有一个NSPredicate 没有的角色t 喜欢。 我删除并重新键入(确切地说?)我将值分配给 orgName 的代码 - 现在它在没有引号的情况下工作。我投票赞成当前的答案,因为响应者花时间考虑我的问题 - 并为这个问题的访问者提出了很好的观点。

标签: ios swift nspredicate cncontactviewcontroller


【解决方案1】:

swift 4 - Xcode 9.1

试试这个

let predicate = NSPredicate(format: "name contains[c] %@ ",searchString)

【讨论】:

    【解决方案2】:

    您应该删除引号。正如Predicate Programming Guide 所说:

    单引号或双引号变量(或替换变量字符串)会导致 %@、%K 或 $variable 在格式字符串中被解释为文字,从而防止任何替换。

    以下两项都对我有用 predicateForEnablingContact。对于我使用的完全匹配:

    let orgName = "Apple"
    let predicate = NSPredicate(format: "organizationName == %@", orgName)
    

    或者,对于通配符搜索:

    let orgName = "CREATIVE*"
    let predicate = NSPredicate(format: "organizationName LIKE[CD] %@", orgName)
    

    【讨论】:

    • LIKE[] 里面的“D”是干什么用的?
    • 变音符号不敏感。例如cd,查找JoséJose
    【解决方案3】:

    我认为您为NSPredicate 选择了错误的初始化。

    init(格式:字符串,参数:CVaListPointer)

    通过将参数列表中的值替换为格式字符串并解析结果来初始化谓词。

    您可以参考NSPredicate 的文档。

    我已经为您的查询尝试了相同的初始化:

    var orgName = "xyz"
    let predicate = NSPredicate(format: "organizationName == %@", orgName)
    print(predicate) // organizationName == "xyz"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多