fbpx
How to add Search in UITableView using Swift

How to add Search in UITableView using Swift

Today, I’m going to show you how to search for items in a UITableView using the UISearchBar.

In this example, we have a UITableView already set up, and the only thing we do is to add the searching functionality.

We have a list of countries as sample data and using the search bar we get the country we want faster.

Adding Search Bar on TableView

Add the UISearchBar at the top of your UITableView.

… and give the name searchBar.

In the ViewController add a Boolean called searching to know when to switch between the full list of items and the list of items from the searching results.

Also add two arrays, countryList and searchedCountry, for all items and the items from the searched results, respectively.

class TableView: UIViewController {

    @IBOutlet var searchBar: UISearchBar!
    
    @IBOutlet var tableView: UITableView!
    
    var countryList = [String]()
    
    var searchedCountry = [String]()
    
    var searching = false
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self
        
        self.listOfCountries()
    }
    
    // Country Names
    func listOfCountries() {
        for code in NSLocale.isoCountryCodes as [String] {
            let id = NSLocale.localeIdentifier(fromComponents: [NSLocale.Key.countryCode.rawValue: code])
            let name = NSLocale(localeIdentifier: "en").displayName(forKey: NSLocale.Key.identifier, value: id) ?? "Country not found for code: \(code)"
            countryList.append(name + " " + countryFlag(country: code))
            tableView.reloadData()
        }
    }
    
    // Add Flag Emoji
    func countryFlag(country: String) -> String {
        let base: UInt32 = 127397
        var s = ""
        for v in country.unicodeScalars {
            s.unicodeScalars.append(UnicodeScalar(base + v.value)!)
        }
        return String(s)
    }
}

In the numberOfRowsInSection method, when searching is true, then will return the number of the items from the search results, and when is not, will return all items.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searching {
            return searchedCountry.count
        } else {
            return countryList.count
        }
    }

In cellForRowAt method, will do the same thing, but this time will return the country’s name for each row.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        if searching {
            cell.textLabel?.text = searchedCountry[indexPath.row]
        } else {
            cell.textLabel?.text = countryList[indexPath.row]
        }
        return cell
    }

… and also the same when you select a cell using the didSelectRowAt method.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if searching {
            let selectedCountry = searchedCountry[indexPath.row]
            print(selectedCountry)
        } else {
            let selectedCountry = countryList[indexPath.row]
            print(selectedCountry)
        }
        // Close keyboard when you select cell
        self.searchBar.searchTextField.endEditing(true)
    }

Create an extension for UISearchBarDelegate.

class TableView: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
        self.searchBar.delegate = self
    }
  
}

extension TableView: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        
    }
    
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {

    }
}

In searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) method, which is called every time we typing, pass the results to the searchedCountry array after using filter to detect if the text we typing in the search bar matches an item in the list.

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchedCountry = countryList.filter { $0.lowercased().prefix(searchText.count) == searchText.lowercased() }
        searching = true
        tableView.reloadData()
    }

… and when we press the Cancel button:

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searching = false
        searchBar.text = ""
        tableView.reloadData()
    }

Customizing the Search Bar

Change the color of the glass icon:

class TableView: UIViewController {

    @IBOutlet var searchBar: UISearchBar!
    
    @IBOutlet var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ... 
   
        let glassIconView = searchTextField.leftView as! UIImageView
        glassIconView.image = glassIconView.image?.withRenderingMode(.alwaysTemplate)
        glassIconView.tintColor = UIColor.red
        
        // ...
        
    }
}

Change the color of the text field inside the search bar:

class TableView: UIViewController {

    @IBOutlet var searchBar: UISearchBar!
    
    @IBOutlet var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ... 
   
        let searchTextField = self.searchBar.searchTextField
        searchTextField.textColor = UIColor.white
        searchTextField.clearButtonMode = .never
        searchTextField.backgroundColor = UIColor.black
        
        // ...
        
    }
}

Hide or show the Cancel button on the right side of search bar:

class TableView: UIViewController {

    @IBOutlet var searchBar: UISearchBar!
    
    @IBOutlet var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ... 
   
        self.searchBar.showsCancelButton = true
        
        // ...
        
    }
}
You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments