Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

February 16, 2015
Shrikar Archak

One of the most important feature in an iOS application would be searching functionality, today we will be learning how to add search to our tableview application in Swift using UISearchBar and UISearchBarDelegate

UISearchBar

The UISearchBar class implements a text field control for text-based searches. The control provides a text field for entering text, a search button, a bookmark button, and a cancel button. The UISearchBar object does not actually perform any searches. You use a delegate, an object conforming to the UISearchBarDelegate protocol, to implement the actions when text is entered and buttons are clicked. You can hide and show the cancel button by setting showsCancelButton to false or true.

UISearchBarDelegate

The UISearchBarDelegate protocol defines the optional methods you implement to make a UISearchBar control functional. A UISearchBar object provides the user interface for a search field on a bar, but it’s the application’s responsibility to implement the actions when buttons are tapped. At a minimum, the delegate needs to perform the actual search when text is entered in the text field.

The main function which we will be implementing are

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

We will maintain a boolean variable searchActive to decide if the search is in progress.

Steps to implement search

  • Create a single view application. Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

  • Disable Size classes for now. Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

  • Select the tableview and set the autolayout constraints to 0. Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

If you are interested in learning iOS Development I suggest you take a look at [Build an app every month]

  • To the existing controller add the tableview and a tableview cell on top of the tableview.Select the tableview Cell go to the attribute inspect and provide the identifier as Cell Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

  • Select the view controller. Select Editor > Embed In > Navigation Controller. Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

  • Create IBOutlet from tableview and the searchbar. CTRL+DRAG from tableview and searchbar to the viewcontroller.swift Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

  • Lets conform to the UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate. Also in viewDidLoad set the datasource and delegate to self.

/* Setup delegates */
tableView.delegate = self;
tableView.dataSource = self;
searchBar.delegate = self;
  • Search functionality is very simple. We just filter the data array and if it matches the text we create a new array called filtered which holds the text which matches the text in the searchbar.
  • Depending on the searchActive we return either the filtered or the actual data in the numberOfRowsInSection and cellForRowAtIndexPath

Below is the complete code required to implement the functionality.

//
//  ViewController.swift
//  SwiftSearch
//
//  Created by Shrikar Archak on 2/16/15.
//  Copyright (c) 2015 Shrikar Archak. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate{

    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var tableView: UITableView!

    var searchActive : Bool = false
    var data = ["San Francisco","New York","San Jose","Chicago","Los Angeles","Austin","Seattle"]
    var filtered:[String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        /* Setup delegates */
        tableView.delegate = self
        tableView.dataSource = self
        searchBar.delegate = self

    }

    func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
        searchActive = true;
    }

    func searchBarTextDidEndEditing(searchBar: UISearchBar) {
        searchActive = false;
    }

    func searchBarCancelButtonClicked(searchBar: UISearchBar) {
        searchActive = false;
    }

    func searchBarSearchButtonClicked(searchBar: UISearchBar) {
        searchActive = false;
    }

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

        filtered = data.filter({ (text) -> Bool in
            let tmp: NSString = text
            let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
            return range.location != NSNotFound
        })
        if(filtered.count == 0){
            searchActive = false;
        } else {
            searchActive = true;
        }
        self.tableView.reloadData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if(searchActive) {
            return filtered.count
        }
        return data.count;
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell;
        if(searchActive){
            cell.textLabel?.text = filtered[indexPath.row]
        } else {
            cell.textLabel?.text = data[indexPath.row];
        }

        return cell;
    }
}

Initial Load Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

On text in the textbar Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

If you want to implement search using parse take a look at this tutorial Parse search in iOS8 with Swift Please let me know if you have any feedback or questions.

Requested tutorials from readers

Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

To get this functionality we need to add these 3 function. First we need to change the style of the tableview from plain to grouped. Next we need to tell the height of the tableview header which in our case is 44. Also we need to creat a segmentedControl and return the control for TableView viewForHeaderInSection. In our case we want to change the data when segmented view Control value is changed. So we will addTarget to the segmentedControl which will be called when the value is changed.

    /* Create these variable to hold different data *.
    var data = ["San Francisco","New York","San Jose","Chicago","Los Angeles","Austin","Seattle"]
    var data0 = ["San Francisco","New York","San Jose","Chicago","Los Angeles","Austin","Seattle"]
    var data1 = ["Data1","Data11","Data111"]
    var data2 = ["Data2","Data22","Data222"]

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let control = UISegmentedControl(items: ["Seg1","Seg2","Seg3"])
        control.addTarget(self, action: "valueChanged:", forControlEvents: UIControlEvents.ValueChanged)
        if(section == 0){
            return control;
        }
        return nil;
    }

    func valueChanged(segmentedControl: UISegmentedControl) {
        println("Coming in : (segmentedControl.selectedSegmentIndex)")
        if(segmentedControl.selectedSegmentIndex == 0){
            self.data = self.data0
        } else if(segmentedControl.selectedSegmentIndex == 1){
            self.data = self.data1
        } else if(segmentedControl.selectedSegmentIndex == 2){
            self.data = self.data2
        } else {
            self.data = data0
        }
        self.tableView.reloadData()
    }

    func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44.0
    }

Subscribe to the newsletter

Get notified when new content or topic is released.

You won't receive any spam! ✌️