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



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

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: $0.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.我搜索了这个 issu,我发现我可以使用ANY然后输入我要检查的字段名称。

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

注意:我使用的是 Swift 4

我认为要使其正常工作,您需要使对象可用于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: $0.name)
}

你也可以给它一个MyObject进行评估,然后你可以使用属性的名称:

let resultPredicate = NSPredicate(format: "name contains[cd] %@", searchText)
let filtered = allDatasource.filter {
resultPredicate.evaluate(with: $0)
}

在代码中,使用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'

您可以尝试像这样过滤

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

最新更新