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

Ne *_* AS 1 nspredicate ios swift

我有一个自定义对象数组。

class MyObject {
    var code: String!
    var name: String!
}
Run Code Online (Sandbox Code Playgroud)

我想要autocomplete一个textFieldtableView用户开始写作时我显示的一个。我必须根据textField.text. 为此,我向 中添加了一个选择器textField,然后测试数组中是否存在包含textFiled.textusing的元素名称NSPredicate

这是文本字段选择器:

    @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: $0.name)
                })
            } else {
                self.filtredDatasource = self.allDatasource
            }
            self.tableView.reloadData()
        }
Run Code Online (Sandbox Code Playgroud)

当我开始写入名称时,应用程序由于以下错误而崩溃:

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

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

我错了吗?我怎么解决这个问题?

注意:我使用的是 Swift 4

fgu*_*aar 5

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

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

    var code: String
    @objc var name: String
}
Run Code Online (Sandbox Code Playgroud)

谓词是根据您给它的对象进行评估的。在您的情况下,您为其提供一个String. 对于要检查的谓词,您应该使用self

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

let filtered = allDatasource.filter {
    resultPredicate.evaluate(with: $0.name)
}
Run Code Online (Sandbox Code Playgroud)

您还可以给它一个MyObject来评估,然后您可以使用属性的名称:

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

let filtered = allDatasource.filter {
    resultPredicate.evaluate(with: $0)
}
Run Code Online (Sandbox Code Playgroud)

在您的代码中,您使用修饰符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'
Run Code Online (Sandbox Code Playgroud)