Search code examples
arraysswiftuitableviewuisearchbaruisearchbardelegate

UIKit SearchBar Filter Two Arrays in textDidChange


I have two initialized and uninitialized arrays as follows:

var colours: [String] = ["Blue", "Red", "Green", "Yellow"]
var numbers: [Int]    = [11, 12, 13, 14]
var coloursFiltered: [String]?
var numbersFiltered: [Int]?

In my search bar, I could filter only one array in the textDidChange function as follows:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        coloursFiltered = colours.filter({ item -> Bool in
            if searchText.isEmpty { return true }
            return item.lowercased().contains(searchText.lowercased())
        })
        tableView.reloadData()
}

/* Later in the Code */
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return coloursFiltered!.count
}

I need to filter the numbers array as well to match the corresponding indices of the filtered colours array. I cannot do so as I cannot access the current index in the colours.filter function. This is to achieve the following:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    self.tableView.register(UINib.init(nibName: "ItemTableViewCell", bundle: nil), forCellReuseIdentifier: "ItemTableViewCell")
    
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "ItemTableViewCell", for: indexPath) as! ItemTableViewCell
   
    cell.name.text = "\(coloursFiltered![indexPath.row])"
    cell.code.text = ""\(numbersFiltered![indexPath.row])"   // I need this to work
   
    return cell
}

Is there a way to filter two arrays using the same string?


Solution

  • You better have a model

    struct Item {
      let color:String
      let number:Int
    }
    

    Then

    var all = [Item(color:"Blue",number:11),.....]
    var coloursFiltered = [Item]()
    

    And filter it instead

    coloursFiltered = all.filter({ item -> Bool in
      if searchText.isEmpty { return true }
         return item.color.lowercased().contains(searchText.lowercased())
      })
    tableView.reloadData()
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return coloursFiltered.count
    } 
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
        self.tableView.register(UINib(nibName: "ItemTableViewCell", bundle: nil), forCellReuseIdentifier: "ItemTableViewCell") 
        let cell = self.tableView.dequeueReusableCell(withIdentifier: "ItemTableViewCell", for: indexPath) as! ItemTableViewCell
        let item = coloursFiltered[indexPath.row]
        cell.name.text = item.color
        cell.code.text = "\(item.number)"  
        return cell
    }