Search code examples
iosswiftxcodefiltersearchbar

Search bar filter isn't clearing the table when results don't match


I have a working search bar, and now I just need help clearing the table when the search text does not match any item in the array (not including an empty search bar).

I would also like for one of the cells to display a message when no match is found (like "no results available").

Here is my code:

@IBOutlet var searchForTool: UISearchBar!
@IBOutlet var toolTable: UITableView!

var searchActive : Bool = false
    {
    didSet {
        if searchActive != oldValue {
            toolTable?.reloadData()
        }
    }
}

typealias Item = (data: String, identity: String)

var filtered: [Item] = []
var items: [Item] = [
    (data: "  Data1", identity: "A"), (data: "  Data2", identity: "B")
]

override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController?.setNavigationBarHidden(true, animated: false)

    AppState.shared.category = "Alphabetical"

}

@IBAction func backButton(_ sender: Any) {

    if let navController = self.navigationController {
        for controller in navController.viewControllers {
            if controller is ToolsViewController {
                navController.popToViewController(controller, animated: true)
            }
        }
    }
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    filtered = items.filter { item in
        item.data.localizedCaseInsensitiveContains(searchText)
    }

    searchActive = !filtered.isEmpty

    self.toolTable.reloadData()

}

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

    return 1
}

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

    if(searchActive) {
        return filtered.count
    }

    return items.count

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell

    cell.alphabeticalLabel.layer.masksToBounds = true

    if(searchActive) {
        cell.alphabeticalLabel.text = filtered[indexPath.row].data
        cell.alphabeticalLabel.layer.cornerRadius = 10
    } else {
        cell.alphabeticalLabel.text = items[indexPath.row].data
        cell.alphabeticalLabel.layer.cornerRadius = 10
    }

    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let vcName: String
    if searchActive {
        vcName = filtered[indexPath.row].identity
    } else {
        vcName = items[indexPath.row].identity
    }
    let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
    self.navigationController?.pushViewController(viewController!, animated: true)
}
}

I know this isn't the best way of creating search bar functionality, but this is what I've been working with for a while. I'm sure the solution isn't very complicated, but I'm just not having any luck with it.

Any help would be greatly appreciated.


Solution

  • Based on your reply, add the check to see if the search text is empty or not:

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
        if(searchActive) {
            return filtered.count
        }
        else if (searchForTool.text? == "")  { // check if this is "" or nil
            return items.count
       }
       else {
           return 0 // Or 1 if you want to show a cell with "no found" text
       }
    }
    

    You'll need to adjust the cellForRowAtIndexpath similarly. And check wether when the text property of the search bar is nil or the empty string when user has not typed anything