Search code examples
iosswiftuitableviewuisearchbaruisearchbardelegate

Search name or number in `UISearchbar`


In tableViewCell I have userNameLbl with name, userClgLbl with number. I want to search and show data in tableView either name search or number search.

If user search name - based on name I can show data in tableView.
If user search number - based on number I can show data in tableView.

But how to work with both name and number for single search bar. Actually here my data is dynamic from server and number is not phone number.

UISearchBarDelegate added to my class

let searchBar = UISearchBar()
var filteredData: [Any]!
@IBOutlet weak var listTblView: UITableView!

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return filteredData.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    // create a new cell if needed or reuse an old one
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell


    cell.userNameLbl.text = filteredData[indexPath.row] as? String
    cell.userClgLbl.text = clg_uniq[indexPath.row] as? String

    return cell

} 

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    let strArr:[String] = clg_uniq as! [String]
    filteredData = searchText.isEmpty ? clg_uniq : strArr.filter({(dataString: String) -> Bool in
        // If dataItem matches the searchText, return true to include it
        return dataString.range(of: searchText, options: .caseInsensitive) != nil
    })

    DispatchQueue.main.async {
        self.listTblView.reloadData()
    }
    if searchText == "" {
        DispatchQueue.main.async {
            searchBar.resignFirstResponder()
        }
    }
}

//Added these lines after json parsing 
self.filteredData = self.clg_uniq
self.listTblView.reloadData()

My example JSON data is

{"log" =     (
            {
        Name = "Name1";
        "clg_uniq" = 5c640e7b86e35;
    },
            {
         Name = "Name2";
        "clg_uniq" = <null>;
    },
            {
         Name = <null>;
        "clg_uniq" = 5c647af5d5c4d;
    },
            {
         Name = "Name4";
        "clg_uniq" = 5c647a0427253;
    },
            {
         Name = <null>;
        "clg_uniq" = <null>;
    },
            {
         Name = "Name6";
        "clg_uniq" = $cuniq";
    },
 )
}

Solution

  • Add following variables -

    var logArray = [Dictionary<String, Any>]() // For all result
    var searchedLogArray = [Dictionary<String, Any>]() // For filtered result
    var searchActive = false // whenever user search anything
    

    Replace UISearchBarDelegate -

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    
        searchActive = searchText.count > 0 ? true : false
    
        let namePredicate = NSPredicate(format: "Name CONTAINS[c] %@", searchText)
        let clgUniqPredicate = NSPredicate(format: "clg_uniq CONTAINS[c] %@", searchText)
    
        let compoundPredicate = NSCompoundPredicate.init(orPredicateWithSubpredicates: [namePredicate, clgUniqPredicate])
    
        searchedLogArray = logArray.filter({
            return compoundPredicate.evaluate(with: $0)
        })
    
        listTblView.reloadData()
    
    }
    

    Replace UITableViewDataSource -

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
        return searchActive ? searchedLogArray.count : logArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
        // create a new cell if needed or reuse an old one
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
    
        let logDict = searchActive ? searchedLogArray[indexPath.row] : logArray[indexPath.row]
    
        // Name
        if let name = log["Name"] as? String{
    
          cell.userNameLbl.text = name
    
        }else{
    
          cell.userNameLbl.text = ""
    
        }
    
    
        // clg_uniq
        if let clgUniq = log["clg_uniq"] as? String {
    
             cell.userClgLbl.text = clgUniq
    
        }else{
    
             cell.userClgLbl.text = ""
    
        }
    
    
        return cell
    
    }
    

    I hope you are persing response as Dictionary<String, Any>

    Let me know if you are still having any issue.