I'm having a problem that many other users have asked about on StackOverflow (examples: 1, 2, 3).
I'd like to have a fixed search bar when scrolling a tableview. I originally had a UITableViewController
with a UISearchBar
on top.
Most solutions recommended that I should have a UIViewController
with a UISearchBar
and a UITableView
below it. I did exactly this. Below is a screenshot of my interface builder.
This solution doesn't fix it, however :( The search bar still doesn't float, and when scrolling it will hide behind the navigation bar.
I have also tried this solution but I'd rather not have the search bar in the navigation bar itself.
Here's all of my TableView or Search related code (I removed everything irrelevant):
class NumberSelectorViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchControllerDelegate {
@IBOutlet var searchBar: UISearchBar!
@IBOutlet var tableView: UITableView!
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
searchController.searchResultsUpdater = self as UISearchResultsUpdating
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
// NOTE: Removing thie line removes the search bar entirely.
tableView.tableHeaderView = searchController.searchBar
addCancelButton()
}
// MARK: - Table view data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching() == true {
return filteredNumberList.count
}
return NumberList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "numberCell")! as UITableViewCell
if isSearching() == true {
cell.textLabel?.text = filteredNumberList[indexPath.row].NumberName
} else {
cell.textLabel?.text = NumberList[indexPath.row].NumberName
}
return cell
}
// MARK: - Table view delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if isSearching() == true {
selectedNumber = filteredNumberList[indexPath.row]
} else {
selectedNumber = NumberList[indexPath.row]
}
performSegue(withIdentifier: "someSegue", sender: self)
}
// MARK: Searching
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredNumberList = NumberList.filter({ (Number) -> Bool in
return (Number.NumberName?.lowercased().contains(searchText.lowercased()))!
})
tableView.reloadData()
}
// MARK: Search Bar
func isSearching() -> Bool {
return (searchController.isActive && searchController.searchBar.text != "")
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredNumbersList.removeAll()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.tableView.reloadData()
}
extension NumberSelectorViewController: UISearchResultsUpdating {
public func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchText: searchController.searchBar.text!)
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
filterContentForSearchText(searchText: searchController.searchBar.text!)
}
}
}