UISearchController Tutorial: Getting Started

In this tutorial, you’ll build a searchable Candy app based on a standard table view. You’ll add table view search capability, dynamic filtering and an optional scope bar using UISearchController, UISearchBar and friends. By Lorenzo Boaro.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Testing the Scope Bar

Build and run. Try entering some search text and changing the scope.

Scope application

Type in “caramel” with the scope set to “All”. It shows up in the list, but when you change the scope to Chocolate, “caramel” disappears because it’s not a chocolate-type candy. Hurrah!

There’s still one small problem with the app. You haven’t added a results indicator to tell the user how many results they should expect to see. This is particularly important when no results are returned at all, as it’s difficult for the user to distinguish between no results returned and a delay in receiving the answer due to a slow network connection.

Adding a Results Indicator

To fix this, you’re going to add a footer to your view. The user will see this footer when they filter the list of candies, and it will tell them how many candies are in the filtered array.

Start by opening SearchFooter.swift. Here, you have a simple UIView which contains a label as well as a public API that will receive the number of results returned.

Head back to MasterViewController.swift. searchFooter is an IBOutlet for the search footer that the starter project already set up for you. You can find it in the master scene in Main.storyboard, at the bottom of the screen.

Within MasterViewController.swift, add the following to viewDidLoad(), after the spot where you set up the scope bar:

let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(
  forName: UIResponder.keyboardWillChangeFrameNotification,
  object: nil, queue: .main) { (notification) in
    self.handleKeyboard(notification: notification)
}
notificationCenter.addObserver(
  forName: UIResponder.keyboardWillHideNotification,
  object: nil, queue: .main) { (notification) in
    self.handleKeyboard(notification: notification) 
}

These two observers allow you to control the results indicator, which will move up or down based on the visibility of the system keyboard.

Next, add this method to MasterViewController:

func handleKeyboard(notification: Notification) {
  // 1
  guard notification.name == UIResponder.keyboardWillChangeFrameNotification else {
    searchFooterBottomConstraint.constant = 0
    view.layoutIfNeeded()
    return
  }

  guard 
    let info = notification.userInfo,
    let keyboardFrame = info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue 
    else {
      return
  }

  // 2
  let keyboardHeight = keyboardFrame.cgRectValue.size.height
  UIView.animate(withDuration: 0.1, animations: { () -> Void in
    self.searchFooterBottomConstraint.constant = keyboardHeight
    self.view.layoutIfNeeded()
  })
}

Here’s what’s happening with the code you just added:

  1. You first check if the notification is has anything to do with hiding the keyboard. If not, you move the search footer down and bail out.
  2. If the notification identifies the ending frame rectangle of the keyboard, you move the search footer just above the keyboard itself.

In both cases, you manage the distance between the search footer and the bottom of the screen through a constraint represented by an IBOutlet called searchFooterBottomConstraint.

Finally, you need to update the number of results in the search footer when the search input changes. So replace tableView(_:numberOfRowsInSection:) with the following:

func tableView(_ tableView: UITableView,
               numberOfRowsInSection section: Int) -> Int {
  if isFiltering {
    searchFooter.setIsFilteringToShow(filteredItemCount:
      filteredCandies.count, of: candies.count)
    return filteredCandies.count
  }
  
  searchFooter.setNotFiltering()
  return candies.count
}

All you’ve done here is to add in calls to the searchFooter.

Build and run, perform a few searches and watch as the footer updates.

Show filter

Where to Go From Here?

Congratulations! You now have a working app that allows you to search directly from the main table view.

You can download the final project using the Download Materials button at the top or bottom of this tutorial.

All kinds of apps use table views, and offering a search option is a nice touch that improves usability. With UISearchBar and the UISearchController, iOS provides much of the functionality out of the box, so there’s no excuse not to use it. The ability to search a large table view is something that today’s users expect; without it, they won’t be happy campers.

In the meantime, if you have any questions or comments, please join the forum discussion below!