Swift 4:来自 UITextField 和自定义对象数组的 NSPredicate

Swift 4: NSPredicate from UITextField and array of custom object

我有一组自定义对象。

class MyObject {
    var code: String!
    var name: String!
}

我想autocomplete一个textField,因为我有一个tableView,当用户开始写作时我会显示它。我必须根据 textField.text 过滤我的数组数据源。为此,我向 textField 添加了一个选择器,然后我使用 NSPredicate.

测试数组中是否存在包含 textFiled.text 的元素名称

这是文本字段选择器:

    @objc func textFieldDidChange(_ textField: UITextField) {
            if (textField.text?.count != 0 && textField.text != " ") {
                let resultPredicate = NSPredicate(format: "ANY name CONTAINS[c] %@", self.countryTextField.text!)
                print("resultPredicate \(resultPredicate)")
//self.allDatasource type is [MyObject]
                self.filtredDatasource = self.allDatasource.filter({
                    return resultPredicate.evaluate(with: [=12=].name)
                })
            } else {
                self.filtredDatasource = self.allDatasource
            }
            self.tableView.reloadData()
        }

当我开始写名字时,应用程序因以下错误而崩溃:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x6040004215e0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.'

所以问题出在NSPredicate format。我搜索了这个问题,发现我可以使用 ANY 然后输入我要检查的字段名称。

我错了吗?我该如何解决这个问题?

注意:我正在使用 Swift 4

你可以试试这样过滤

let searchText =  self.countryTextField.text

self.filtredDatasource = self.allDatasource.filter { ([=10=].name as! String).range(of: searchText!, options: [.diacriticInsensitive, .caseInsensitive]) != nil }

我认为要使其正常工作,您需要让 Objective-C 端可以使用您的对象:

class MyObject: NSObject {
    init(code: String, name: String) {
        self.code = code
        self.name = name
    }

    var code: String
    @objc var name: String
}

谓词是根据您给它的对象求值的。在你的例子中,你提供了一个 String。对于要检查的谓词,您应该使用 self:

let resultPredicate = NSPredicate(format: "self contains[cd] %@", searchText)

let filtered = allDatasource.filter {
    resultPredicate.evaluate(with: [=11=].name)
}

你也可以给它一个MyObject来求值,然后你就可以使用属性:

的名字
let resultPredicate = NSPredicate(format: "name contains[cd] %@", searchText)

let filtered = allDatasource.filter {
    resultPredicate.evaluate(with: [=12=])
}

在您的代码中,您使用了 ANY 修饰符。这是一个修饰符,您可以使用它来检查集合中是否有 any 项目符合谓词:

let searchText = "n2"
let resultPredicate = NSPredicate(format: "ANY name contains[cd] %@", searchText)

let allDatasource = [ MyObject(code: "c1", name: "n1"), MyObject(code: "c2", name: "n2")]
let containsAnyObject = resultPredicate.evaluate(with: allDatasource)

// true for 'n2'