Search code examples
swiftsearchtableviewcontacts

How to search phone contacts in swift


In project i am getting all my contacts.. here i need to search contacts by their name how to do that

i have done almost but unable to filter in textDidChange

below is my tried code:

class ContactsViewController1: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var joinersTableView: UITableView!
    var contacts = [CNContact]()

    var search = false
    var searchArray = [CNContact]()

    func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            return jsonArrayTagged.count
        } else {
            if search {
                return searchArray.count
            } else {
                return contacts.count
            }
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 1 {
            var cell1: ContactsTableViewCell2 = tableView.dequeueReusableCell(withIdentifier: "ContactsTableViewCell2", for: indexPath) as! ContactsTableViewCell2
            if search {
                cell1.nameLbl.text    = searchArray[indexPath.row].givenName + " " + searchArray[indexPath.row].familyName
                cell1.empRoleLbl.text = searchArray[indexPath.row].phoneNumbers.first?.value.stringValue
                cell1.inviteButn.addTarget(self, action: #selector(connected(sender:)), for: .touchUpInside)
            } else {
                cell1.nameLbl.text    = contacts[indexPath.row].givenName + " " + contacts[indexPath.row].familyName
                cell1.empRoleLbl.text = contacts[indexPath.row].phoneNumbers.first?.value.stringValue
                cell1.inviteButn.addTarget(self, action: #selector(connected(sender:)), for: .touchUpInside)
            }

            return cell1
        }

        return UITableViewCell()
    }
}

extension ContactsViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchArray = contacts.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
        search = true

        joinersTableView.reloadData()
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        search = false
        searchBar.text = ""
        joinersTableView.reloadData()
    }
}

error:

Value of type 'CNContact' has no member 'lowercased'


Solution

  • You can't just use a CNContact as a String and compare it with a String. You need to specify which String property of the CNContact you want to filter.

    If you want to search the familyName for instance, do $0.familyName.lowerCased() instead of $0.lowerCased, since $0 is a CNContact.

    extension ContactsViewController: UISearchBarDelegate {
        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            searchArray = contacts.filter {$0.familyName.lowercased().prefix(searchText.count) == searchText.lowercased()}
            search = true
    
            joinersTableView.reloadData()
        }
    ...
    }
    

    Unrelated to your question, but why are you searching the beginning of the text only? Using localizedCaseInsensitiveContains instead of prefix would yield a much better user experience.