UI Components

VERSION 0.28.2
PUBLIC PREVIEW

SearchUI is a framework that offers ready-to-use UI elements to integrate search functionality into your application. The UI elements include:

The Search UI looks like this with the default configuration:


If you’d like to build a custom UI yourself using the TomTom Search SDK, you can use Search. You can learn more about building a UI in this guide.

SearchView

SearchView is a container view that combines SearchBarView, SearchResultsView and SearchSuggestionsView in a ready-to-use Search UI. By default, SearchView performs a search for the entered query in SearchBarView and displays the results in SearchResultsView. Starting with SearchView is the quickest way to try the TomTom Search SDK. This section will tell you how to create and configure a SearchView:

SearchView is part of TomTomSDKSearchUI, so start by importing that. You also have to import TomTomSDKSearchOnline to use the search service:

import TomTomSDKSearchOnline
import TomTomSDKSearchUI

The online search service requires a OnlineSearch API key. You can get an API key by following the instructions in this guide. After obtaining the API key initialize the search service:

let onlineSearch = OnlineSearch(apiKey: "YOUR_API_KEY")

Now create a SearchViewConfiguration to provide all of the basic settings and dependencies for SearchView. Using this configuration, you can define:

  • Theme - the set of visual attributes that defines the appearance of the Search UI (colors, fonts, etc.).
  • Search - the service that performs search queries.
  • SearchQueryConfiguration - the set of options that defines search functionality.

To create or modify SearchViewConfiguration use SearchViewConfigurationBuilder:

1let builder = SearchViewConfigurationBuilder(
2 searchService: onlineSearch,
3 searchQueryConfiguration: SearchQueryConfiguration()
4)
5
6// Modify configuration parameters using various `.withXXX()` methods
7let configuration = builder.withDistanceUnits(.metric).build()

Once you’ve created and configured SearchViewConfiguration, you can create SearchView either programmatically or via a storyboard.

To create a SearchView instance programmatically use init(withConfiguration:):

let searchView = SearchView(withConfiguration: configuration)

To use SearchView from a storyboard call setup(with:) when view is loaded

1let storyboard = UIStoryboard(name: "MyStoryboard", bundle: .main)
2let viewController = storyboard.instantiateViewController(withIdentifier: "ViewControllerWithSearchView")
3let searchViewFromStoryboard = viewController.view as? SearchView
4searchViewFromStoryboard?.setup(withConfiguration: configuration)

if you created and configured a SearchView instance with an initializer, you don’t need to use setup(with:)

To finish integrating SearchUI into the UX flow of your app, set a SearchViewDelegate. The delegate provides callbacks to receive any search errors that occur, navigates back from the Search UI, and handles selection of the search result.

let controller = SearchController()
searchView.delegate = controller
1extension SearchController: SearchViewDelegate {
2 func tappedBack() {
3 // Called when a user tapped on Back button (indicates the exit from search UI)
4 }
5
6 func didSelectResult(_ result: SearchResult) {
7 // Called when a user selected one of the search results.
8 }
9
10 func onSearchError(_ error: Error) {
11 // Called when an error occurred during the search
12 }
13
14 func onTextUpdated(hasInput: Bool) {
15 // Called when a user updated the text in the Search Bar
16 }
17}
18
19// MARK: - SearchBarController + SearchBarViewDelegate

SearchBarView

This section describes the SearchBarView independently from the other UI components needed to build a custom Search UI experience. If you need a more complete and ready-to-use Search UI solution, see SearchView.

SearchBarView is a crucial part for making search requests from user input. This view consists of a text field to allow the user to enter text, a Clear button for removing entered text, and a Back button to exit the Search UI.


Here are the steps for creating and configuring a SearchBarView:

SearchBarView is part of the TomTomSDKSearchUI. Start by importing that. You also need to import TomTomSDKSearchOnline to use the search service:

import TomTomSDKSearchOnline
import TomTomSDKSearchUI

The online search service requires a OnlineSearch API key. You can get an API key by following the instructions in this guide). After obtaining the API key initialize the search service:

let onlineSearch = OnlineSearch(apiKey: "YOUR_API_KEY")

Next create a SearchBarViewConfiguration that provides all basic settings and dependencies for SearchBarView. Using this configuration, you can define:

  • Theme - a set of visual attributes that define the appearance of Search UI (e.g., colors, fonts, etc.).
  • Search - a service to perform search queries.
  • SearchQueryConfiguration - a set of options that define search functionality.

To create or modify SearchBarViewConfiguration use SearchBarViewConfigurationBuilder:

1let barConfigurationBuilder = SearchBarViewConfigurationBuilder(
2 searchService: onlineSearch,
3 searchQueryConfiguration: SearchQueryConfiguration()
4)
5let barConfiguration = barConfigurationBuilder.build()

Once SearchBarViewConfiguration is created and configured, you can create SearchBarView either programmatically or via a storyboard.

To create a SearchBarView instance programmatically use init(withConfiguration:):

let searchBarView = SearchBarView(withConfiguration: barConfiguration)

To use SearchBarView from a storyboard call setup(with:) when the view is loaded

1let storyboard = UIStoryboard(name: "MyStoryboard", bundle: .main)
2let viewController = storyboard.instantiateViewController(withIdentifier: "ViewControllerWithSearchBar")
3let searchBarFromStoryboard = viewController.view as? SearchBarView
4searchBarFromStoryboard?.setup(withConfiguration: barConfiguration)

if you created and configured a SearchBarView instance with an initializer, you don’t need to use setup(with:)

To connect SearchBarView with other views, such as the results view, create an object that conforms to SearchBarViewDelegate:

1extension SearchBarController: SearchBarViewDelegate {
2 func onSearchError(_ error: Error) {
3 // Called when an error occurred during the search
4 }
5
6 func onFoundResults(_ results: [SearchResult]) {
7 // Called when the search returned a list of places
8 }
9
10 func onTextUpdated() {
11 // Called when a user has updated the text in the Search Bar
12 }
13}

Then set the object that conforms to SearchBarView to the search bar .delegate property:

let searchBarController = SearchBarController()
searchBarView.delegate = searchBarController

The delegate defines several methods that describe the lifecycle of user interactions with SearchBarView:

  1. Whenever the user changes the text in the search bar text field, the delegate calls onTextUpdated()
  2. If the field already contains text, the search engine is automatically triggered to start searching for the entered phrase. There are 2 possible results of that search:

To change the input state of the SearchBarView programmatically, use .searchQuery:

let searchBarController = SearchBarController()
searchBarView.delegate = searchBarController

SearchResultsView

Once you have search results, the TomTom SDKs can help you show them to the user. Use SearchResultsView to present search results as a list. By default, SearchResultsView shows the name of the place, its address, and the distance from the current location. If no places are available, the results view displays "No results yet".


Like SearchBarView and SearchView, the results view can be initialized programmatically with a viewModel argument or configured from a storyboard after the view is loaded. Both approaches require a SearchResultsViewModel instance. To create a SearchResultsViewModel you need to pass 3 entities: a theme, the places returned by the search, and the distance unit type.

1let viewModel = SearchResultsViewModel(
2 theme: SearchingTheme.default,
3 results: [],
4 distanceUnits: Locale.current.unitSystem
5)

To create a results view without a storyboard use .init(withViewModel):

let resultsView = SearchResultsView(withViewModel: viewModel)

To set up the results view after loading it from a storyboard, use setup(withViewModel:):

1let storyboard = UIStoryboard(name: "MyStoryboard", bundle: .main)
2let viewController = storyboard.instantiateViewController(withIdentifier: "ViewControllerWithSearchResults")
3let searchResultsFromStoryboard = viewController.view as? SearchResultsView
4searchResultsFromStoryboard?.setup(withViewModel: viewModel)

if you created and configured a SearchResultsView instance with an initializer, you don’t need to use setup(withViewModel:)

To update the displayed search results, use the update(withPlaces:query) method. This method requires a list of Place objects returned from the search. It also takes an optional query to highlight matching results.

1var results = [SearchResult]()
2
3// Pass an actual query used for search, for example from a `SearchBarView.searchQuery`
4let query = "REPLACE_THIS_CONSTANT_WITH_ACTUAL_SEARCH_QUERY"
5
6// Fill places with the results of a search
7resultsView.update(withResults: results, query: query)

If an error occurred, call displayError(error:) to display the error message.

resultsView.display(error: "Couldn't fetch search results. Check your Internet connection.")

You can also clear all the results from the SearchResultsView in the code:

resultsView.clear()