Поиск контактов с использованием NSExpressions и NSPredicates

Мне удалось отфильтровать таблицу контактов по имени, фамилии, компании и заметкам. Однако мне также нужно иметь возможность искать по почтовым адресам контакта условия поиска. Кто-нибудь работал с этим раньше и знает, как это сделать, используя методологию NSExpression/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()
}

0 ответов

Другие вопросы по тегам