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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
UISearchController Tutorial: Getting Started
20 mins
- Getting Started
- Populating the Table View
- Introducing UISearchController
- Setting Up searchController‘s Parameters
- Filtering With UISearchResultsUpdating
- Updating the Table View
- Sending Data to a Detail View
- Creating a Scope Bar to Filter Results
- Testing the Scope Bar
- Adding a Results Indicator
- Where to Go From Here?
Testing the Scope Bar
Build and run. Try entering some search text and changing the scope.
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:
- 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.
- 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.
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!