What’s New With UISearchController and UISearchBar
In this UISearchController tutorial, you’ll learn about UISearchToken, UISearchTextField and other new APIs introduced in iOS 13. By Corey Davis.
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
What’s New With UISearchController and UISearchBar
25 mins
- Getting Started
- Using the Search Results Controller
- Displaying Results: You’re in Control
- Everything You Need to Know About Search Tokens
- Creating Tokens
- Making a UI for Selecting Tokens
- Adding Tokens to the Search Bar
- Modifying Your Search to Use Tokens
- Hiding the Scope Bar
- Customizing the Search Bar and Text Field
- Changing Text and Background Color
- Changing the Color of Tokens
- Where to Go From Here?
UISearchBar
and UISearchController
are staples of iOS app development. But while UISearchBar
has received periodic changes since its introduction in iOS 2, UISearchController
has been pretty static since Apple introduced it in iOS 8. In iOS 13, Apple updated both.
Apple also introduced UISearchToken
, which provides much-needed power to UISearchController
. With very little effort, you can enable your users to perform complex search queries in addition to the text-based searches they’re used to.
If you’ve ever written tedious, fragile code to traverse the search bar’s view hierarchy to get a reference to the search text field, there is more good news. The UISearchTextField
is now exposed as a property, making customization much easier.
In this tutorial, you’ll learn:
- How to control the search results controller’s display.
- Everything there is to know about search tokens.
- How to create and use search tokens.
- How to customize
UISearchController
, the search bar and its text field.
UISearchController
is new to you, read UISearchController Tutorial: Getting Started first.
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
Throughout this tutorial, you’ll work on L.I.S.T.E.D., the Large International Sorted Tally of Earth Dwellers. L.I.S.T.E.D. is an organization that keeps track of the total population of the world. They currently have populations for all countries for the years 2018 and 2019.
Anticipating the release of 2020 population data, they want to expand their search capabilities. As an Earth dweller yourself, you’re going to help refactor the app and bring its search functionality to a whole new level for the organization.
Start by opening LISTED.xcodeproj inside the starter folder, then open Main.storyboard.
You’ll see the app is pretty simple. There are only two view controllers, which are wrapped inside a navigation controller.
Build and run. You’ll see this:
Now, search for “new”. You’ll see these search results:
The result displays matches for all years. Tapping 2018 or 2019 in the scope bar will narrow the search. Try it now by tapping 2019 and this is what you’ll see:
Great, basic searching works fine. Now, you’ll make it better!
Using the Search Results Controller
UISearchController
provides two options for displaying results: displaying them in the same view that shows the original data or using a search results controller.
L.I.S.T.E.D. uses a search results controller to display the results in a slightly different format from the main controller. When the user taps into the search bar, the main view controller remains visible. The result view controller displays after the user starts typing the search.
Before iOS 13, you had little control over this behavior, but now you can use the newly-added showsSearchResultsController
in UISearchController
to customize your results. You’ll see how in the next sections.
Displaying Results: You’re in Control
To control when search results display, you need to react to changes in the search bar. For this to work, the main view controller will conform to UISearchResultsUpdating
.
The delegate receives a call to updateSearchResults(for:)
when the search bar becomes the first responder or when text changes. You’ll use this to trigger the display of the results controller.
Open MainViewController.swift and add the following after UISearchBarDelegate
:
// MARK: -
extension MainViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
searchController.showsSearchResultsController = true
}
}
The search results now display when the search bar becomes the first responder.
Before you can test that, add the following code as the last line in viewDidLoad()
:
searchController.searchResultsUpdater = self
The search results updater is responsible for updating the search results controller. Here, you’re assigning that responsibility to the main controller.
Build and run. Tap the search bar and you’ll see an empty search results controller.
You’re now in full control of showing — and hiding — the search results. As powerful as you must feel now, showing a blank results controller is not a great user experience. You’ll address that soon, but first, you need to know more about search tokens.
Everything You Need to Know About Search Tokens
Search tokens are arguably the most interesting feature Apple added to search in iOS 13. If you use Apple’s Mail or Photos apps on iOS 13, you’ve likely already seen search tokens in action.
The Mail app uses search tokens to create complex searches. Tapping the search bar shows suggestions like “unread messages” and “flagged messages”.
Tokens can represent complex searches like searching by geolocation or simple searches using predetermined text. The key to search tokens is representedObject
in UISearchToken
.
representedObject
is an Any?
and can contain any type of data that’s useful to you.
It’s important to keep in mind that representedObject
is strongly referenced. Any object it holds may stick around for quite some time. Use lightweight data to avoid problems. String
s, Int
s and NSManagedObjectID
s are great candidates.
Creating Tokens
It’s time to address the empty search results view you see when you tap the search bar. This is a great place to show a list of tokens available to your users.
Open ResultsTableViewController.swift. At the top of the class, after countries
, add the following:
var searchTokens: [UISearchToken] = []
Here, you’re creating an array to hold the search tokens. After that line, add the following:
var isFilteringByCountry: Bool {
return countries != nil
}
This computed Boolean will return true
when users are searching or false
when they’re not. You’ll use it soon.
At the end of the file, below the class, add the following extension:
// MARK: -
extension ResultsTableViewController {
func makeTokens() {
// 1
let continents = Continent.allCases
searchTokens = continents.map { (continent) -> UISearchToken in
// 2
let globeImage = UIImage(systemName: "globe")
let token = UISearchToken(icon: globeImage, text: continent.description)
// 3
token.representedObject = Continent(rawValue: continent.description)
// 4
return token
}
}
}
This code does the following:
- Creates an array of all continents.
- Creates an image that represents the token. Next, using the image and current continent’s description, it creates a search token.
- Assigns the continent’s description to the token’s
representedObject
. You’ll use this later to narrow searches to specific continents. Using a lightweight value such as a string is perfect for this situation. - Returns the token, which appends to
searchTokens
, which you created earlier.
In viewDidLoad()
, add this as the last line:
makeTokens()
Here, you create the search tokens when the view loads. That’s it! Creating search tokens is that simple. :]
Before you build and run again, you need to update the results controller to display these new tokens. You’ll do that in the next step.