skip to Main Content

I am trying to search contact in my app. I am using search bar to do that.

Lets suppose that I have a 2 contacts, Tolga and Toygun. When I type for "To" in searchbar both contact appears in table view. Then I type for "Toy" in searchbar no one appears in table view as should be. The problem is when I delete the letter y in "Toy" no one continues to appear. I want to see both contact in table view when I delete letter y but I couldn’t.

Here is my code:

class ContactsVC: UIViewController {
    
    //MARK: - Proporties
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var emptyView: UIView!
    
    
    let fireStoreDatabase = Firestore.firestore()
    var contactArray = [Contact]()
    var tempContactArray = [Contact]()
    var letters: [Character] = []
    var tempLetters: [Character] = [] 

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        
        searchBar.delegate = self
        hideKeyboardWhenTappedAround()
        getDataFromFirebase()
    }
    
    //MARK: - Function to Get Contacts Data From Firebase
    func getDataFromFirebase(){
        fireStoreDatabase.collection("Contacts").order(by: "contactName").addSnapshotListener { (snapshot, err) in
            if err == nil {
                if snapshot?.isEmpty == false && snapshot != nil {
                    self.contactArray.removeAll(keepingCapacity: false)
                    for document in snapshot!.documents {
                        if let uid = document.get("uid") as? String {
                            if uid == self.userId {
                                if let contactUrl = document.get("contactUrl") as? String,
                                   let contactName = document.get("contactName") as? String,
                                   let contactSirname = document.get("contactSirname") as? String,
                                   let contactPhone = document.get("contactPhone") as? String,
                                   let contactEmail = document.get("contactEmail") as? String,
                                   let contactBloodgroup = document.get("contactBloodGroup") as? String,
                                   let contactBirthday = document.get("contactBirthday") as? String{
                                    
                                    self.contactArray.append(Contact(contactUrl: contactUrl, contactName: contactName, contactSirname: contactSirname, contactPhone: contactPhone, contactEmail: contactEmail, contactBloodgroup: contactBloodgroup, contactBirthday: contactBirthday, documentId: document.documentID))
                                }
                                
                            }
                        }
                    }
                    self.tempContactArray = self.contactArray
                    
                    //Section
                    self.letters.removeAll(keepingCapacity: false)
                    self.letters = self.contactArray.map({ (contact) in
                        return contact.contactName.uppercased().first!
                    })
                    self.letters = self.letters.sorted()
                    self.letters = self.letters.reduce([], { (list, name) -> [Character] in
                        if !list.contains(name) {
                            return list + [name]
                        }
                        return list
                    })
                    self.tempLetters = self.letters
                    self.tableView.reloadData()
                    
                } else {
                    self.contactArray.removeAll(keepingCapacity: false)
                    self.tableView.reloadData()
                }
                
                if(self.contactArray.count == 0) {
                    self.emptyView.isHidden = false
                    self.tableView.isHidden = true
                }else{
                    self.emptyView.isHidden = true
                    self.tableView.isHidden = false
                }
            }
        }
    }
    
    //MARK: - Section after search
    func getLetters(contact: [Contact]) {
       
       letters.removeAll(keepingCapacity: false)
       letters = contact.map({ (contact) in
           return contact.contactName.uppercased().first!
       })
       letters = letters.sorted()
       letters = letters.reduce([], { (list, name) -> [Character] in
           if !list.contains(name) {
               return list + [name]
           }
           return list
       })
    }
    
//MARK: - Table View Data Source
extension ContactsVC: UITableViewDelegate, UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        letters.count
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return letters[section].description
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return contactArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ContactsViewCell
        
        if letters[indexPath.section] == contactArray[indexPath.row].contactName.uppercased().first {
            cell.contactImage.sd_setImage(with: URL(string: contactArray[indexPath.row].contactUrl))
            cell.contactFullNameLabel.text = contactArray[indexPath.row].contactName + " " + contactArray[indexPath.row].contactSirname
        }
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if letters[indexPath.section] == contactArray[indexPath.row].contactName.uppercased().first {
            return 100.0
        } else {
            return 0.0
        }
    }
    
   
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(identifier: "AddContactVC") as! AddContactVC
        vc.isNewContact = false
        vc.documentId = contactArray[indexPath.row].documentId
        vc.contact = contactArray[indexPath.row]
        self.present(vc, animated: true, completion: nil)
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        view.endEditing(true)
    }
    
}

//MARK: - Search Bar
extension ContactsVC: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        print(searchText)
        letters.removeAll(keepingCapacity: false)
        if searchText.isEmpty == false {
            contactArray = contactArray.filter{$0.contactName.lowercased().contains(searchText.lowercased())}
            getLetters(contact: contactArray)
        } else {
            contactArray = tempContactArray
            letters = tempLetters
        }
        
        self.tableView.reloadData()
        
    }
    
}

2

Answers


  1. You can also implement UISearchController UISearchResultsUpdating protocol with function updateSearchResults and handle all your changes there. Here is a smooth tutorial: https://www.raywenderlich.com/4363809-uisearchcontroller-tutorial-getting-started

    Login or Signup to reply.
  2. This line causes the problem.

    contactArray = contactArray.filter{$0.contactName.lowercased().contains(searchText.lowercased())}

    let’s consider the same example you mentioned. You have two contacts ‘Tolgo’ and ‘Toygun’. When you type ‘To’, You filter the contacts and again assign it to the contactArray. So now contactArray will have two contacts Tolgo and Toygun. When you type ‘Toy’, again you apply filter on those 2 contacts in contactArray and assign to contactArray again. Now you will have only one contact detail ‘Toygun’ in contactArray. You are deleting ‘y’ from ‘toy’ search keyword, now you apply filter on contactArray which only has one contact(toygun). This causes only one contact to show in table

    Solution:

    Have all your fetched contacts in contactArray. On searching, filter from this array and assign the filtered items to tempContactArray. Have tempContactArray as the source array.

    I hope i am able to help you solve your problem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search