Home > OS >  How to add a searchbar to tableview in swift?
How to add a searchbar to tableview in swift?

Time:09-17

I am trying to add in a search bar function to actually filter my data. I have been able to generate the data that I need and populate it into a tableview. However, when I go to search using the following code, the searching variable always comes back as false so the tableview never gets updated.

// MARK: - Search Bar
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    searching = true
    searchstuff = stuff.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
    print(searching)
    self.tableView.reloadData()
}

// Cancel button for when one is searching
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searching = false
    self.searchBar.endEditing(true)
    self.tableView.reloadData()
}

// MARK: - Keyboard Dismiss
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    self.searchBar.endEditing(true)
}

// Make sure to back out of the search bar when clicked else where
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    self.searchBar.endEditing(true)
}

// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    tableView.backgroundColor = .black
    if searching == true {
        return searchstuff.count
    }
    else {
        return stuff.count
    }
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let stuffProfileVC = searchstuff(collectionViewLayout: UICollectionViewLayout())
    navigationController?.pushViewController(stuffProfileVC, animated: true)
    titles = searchstuff[indexPath.row]
}

// This is the table view for each individual stuff name
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! SearchStuff
    cell.textLabel?.textColor = .white
    cell.backgroundColor = .black
    print(searching)
    if searching == true {
        cell.textLabel?.text = searchstuff[indexPath.row]
    }
    else {
        cell.textLabel?.text = stuff[indexPath.row]
    }
    return cell
}

CodePudding user response:

If you are using UINavigationController , you can easily implement UISearchController

let searchController = UISearchController(searchResultsController: nil)

    private func setSearchController() {
    searchController.searchBar.placeholder = "Search".localized
    searchController.searchResultsUpdater = self
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.delegate = self
    navigationItem.searchController = searchController
    definesPresentationContext = true
}

    override func viewDidLoad() {
    super.viewDidLoad()
    setSearchController()
}

CodePudding user response:

class MainTableViewController: UITableViewController {
    
    let searchBarController = UISearchController(searchResultsController: nil)
    let listData = ["Sam", "Jam", "Tam", "Pam", "Kam", "Nam", "Mam"]
    var filteredData = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Demo"
        setSearchBarUI()
        getFilteredData()
    }
    
    func setSearchBarUI() {
        searchBarController.searchBar.delegate = self
        searchBarController.obscuresBackgroundDuringPresentation = false
        searchBarController.searchBar.sizeToFit()
        navigationItem.searchController = searchBarController
    }

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return filteredData.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SearchStuff", for: indexPath) as! SearchStuff
        cell.titleLabel.text = filteredData[indexPath.row]
        return cell
    }
    
    func getFilteredData(searchedText: String = String()) {
        let filteredListData: [String] = listData.filter({ (object) -> Bool in
            searchedText.isEmpty ? true : object.lowercased().contains(searchedText.lowercased())
        })
        filteredData = filteredListData
        tableView.reloadData()
    }

}

extension MainTableViewController: UISearchBarDelegate {
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        getFilteredData(searchedText: searchBar.text ?? String())
    }
    
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        searchBar.endEditing(true)
    }
    
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.endEditing(true)
        searchBar.text = String()
        getFilteredData()
    }
    
}

Output:

enter image description here

This way you can ignore using the searching variable for handling different states of the table view.

  • Related