Swift – Search Bar Tutorial
In this tutorial we are going to implement a search bar that will be able to search a table view, this will filter the results to only show the items you searched for dynamically. You can download the starter app here, we have a table which looks like the following:
As you can see we have a few cupcakes and the size of them. Our goal is to enable the user to search for the sweet sweet cupcake of their desires. The starting code in the ViewController.swift looks like the following:
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet var tableView: UITableView! struct Cake { var name = String() var size = String() } var cakes = [Cake(name: "Red Velvet", size: "Small"), Cake(name: "Brownie", size: "Medium"), Cake(name: "Bannna Bread", size: "Large"), Cake(name: "Vanilla", size: "Small"), Cake(name: "Minty", size: "Medium")] override func viewDidLoad() { super.viewDidLoad() self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") self.tableView.reloadData() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.cakes.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "cell") cell.textLabel?.text = self.cakes[indexPath.row].name cell.detailTextLabel?.text = self.cakes[indexPath.row].size return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("Row \(indexPath.row) selected") } }
To add a search bar we will do so by coding it which is fairly easy, it just requires a bit of setup at first. First off all add the UISearchResultsUpdating to the class declaration:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
Next add the following class level variable which will hold the filtered search results:
var filteredCakes = [Cake]()
Then change viewDidLoad to the following:
override func viewDidLoad() { super.viewDidLoad() filteredCakes = cakes searchController.searchResultsUpdater = self searchController.dimsBackgroundDuringPresentation = false definesPresentationContext = true tableView.tableHeaderView = searchController.searchBar self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") }
In this we do the following:
- Store the tableData in filteretedTableData
- Setup the searchController, this will add it to our table view
Then change the numbeOfRowsInSection and cellForRow at indexPath for the table view delegate. We are changing the cakes instances to filteredCakes, so when we search it will show the filtered results.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.filteredCakes.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "cell") cell.textLabel?.text = self.filteredCakes[indexPath.row].name cell.detailTextLabel?.text = self.filteredCakes[indexPath.row].size return cell }
Now finally add the following function which will run whenever we type in the search bar, this is triggered by the UISearchResultsUpdating we added.
func updateSearchResults(for searchController: UISearchController) { // If we haven't typed anything into the search bar then do not filter the results if searchController.searchBar.text! == "" { filteredCakes = cakes } else { // Filter the results filteredCakes = cakes.filter { $0.name.lowercased().contains(searchController.searchBar.text!.lowercased()) } } self.tableView.reloadData() }
It works in the following way:
- If the search bar is empty then show all the results
- If we have something typed into the search bar then filter on it, this is done by the cakes.name.filter. This works by checking every item in cakes and seeing if it matches the filter as follows:
- The $0 represents the current item it is searching on
- We then convert it to lowercase to be case insensitive
- We check if this current cake item contains any text that the user has typed into the search bar
- The search bar text is also converted to lower case
- Finally once it has found all items that match this condition it places them in the filteredCakes Array
- We finally reload the tableview for the updated results
Now you can run your app and see the search works as follows: