我已经能够通过联系人的名字,姓氏,公司和备注来过滤联系人表格。但是,我还需要能够在联系人的邮政地址中搜索搜索字词。有没有人以前使用过NSEpression / NSPredicate方法,而不是简单地循环访问联系人?
我有超过6000个联系人要经历这样的循环并不是非常有效。我已经开始尝试解决这个问题了,但我却失败了。我一直收到以下错误:由于未捕获的异常终止应用程序' NSUnknownKeyException',原因:' [valueForUndefinedKey:]:此类不是关键城市的键值编码兼容。 ' ,但我知道我在提取联系人时提供了描述符。再次,我们非常感谢您的帮助,并且我已在下面粘贴了我的代码。
func updateSearchResults(for searchController: UISearchController) {
// Update the filtered array based on the search text.
let searchResults = contacts
// Strip out all the leading and trailing spaces.
let whitespaceCharacterSet = CharacterSet.whitespaces
let strippedString = searchController.searchBar.text!.trimmingCharacters(in: whitespaceCharacterSet)
let searchItems = strippedString.components(separatedBy: " ") as [String]
// Build all the "AND" expressions for each value in the searchString.
let andMatchPredicates: [NSPredicate] = searchItems.map { searchString in
var searchItemsPredicate = [NSPredicate]()
// Key Path field matching.
let firstNameExpression = NSExpression(forKeyPath: CNContactGivenNameKey)
let lastNameExpression = NSExpression(forKeyPath: CNContactFamilyNameKey)
let companyNameExpression = NSExpression(forKeyPath: CNContactOrganizationNameKey)
let noteExpression = NSExpression(forKeyPath: CNContactNoteKey)
//let addressesExpressions = NSExpression(forKeyPath: CNPostalAddressCityKey)
var searchStringExpression: NSExpression!
if searchString == "$" || searchString == "$$" {
searchStringExpression = NSExpression(forConstantValue: "customer")
} else {
searchStringExpression = NSExpression(forConstantValue: searchString)
}
let firstNameSearchComparisonPredicate = NSComparisonPredicate(leftExpression: firstNameExpression, rightExpression: searchStringExpression, modifier: .direct, type: .contains, options: .caseInsensitive)
let lastNameSearchComparisonPredicate = NSComparisonPredicate(leftExpression: lastNameExpression, rightExpression: searchStringExpression, modifier: .direct, type: .contains, options: .caseInsensitive)
let companyNameSearchComparisonPredicate = NSComparisonPredicate(leftExpression: companyNameExpression, rightExpression: searchStringExpression, modifier: .direct, type: .contains, options: .caseInsensitive)
let noteSearchComparisonPredicate = NSComparisonPredicate(leftExpression: noteExpression, rightExpression: searchStringExpression, modifier: .direct, type: .contains, options: .caseInsensitive)
//let addressesSearchComparisonPredicate = NSComparisonPredicate(leftExpression: addressesExpressions, rightExpression: searchStringExpression, modifier: .direct, type: .contains, options: .caseInsensitive)
searchItemsPredicate.append(firstNameSearchComparisonPredicate)
searchItemsPredicate.append(lastNameSearchComparisonPredicate)
searchItemsPredicate.append(companyNameSearchComparisonPredicate)
searchItemsPredicate.append(noteSearchComparisonPredicate)
//searchItemsPredicate.append(addressesSearchComparisonPredicate)
// Add this OR predicate to our master AND predicate.
let orMatchPredicate = NSCompoundPredicate(orPredicateWithSubpredicates:searchItemsPredicate)
return orMatchPredicate
}
// Match up the fields of the Product object.
let finalCompoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: andMatchPredicates)
let filteredResults = searchResults.filter { finalCompoundPredicate.evaluate(with: $0) }
// Hand over the filtered results to our search results table.
self.filteredContacts = filteredResults
self.tableView.reloadData()
}