UI Components

VERSION 0.45.0
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 the quickstart guide.

SearchView

SearchView is a container view that combines SearchBarView, SearchResultsView and SearchSuggestionView 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 an API key. You can get an API key by following the instructions in the quickstart guide. After obtaining the API key, initialize the search service:

let onlineSearch = OnlineSearchFactory.create(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 define 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 SearchView.init(withConfiguration:):

let searchView = SearchView(withConfiguration: configuration)

To use SearchView from a storyboard call SearchView.setup(withConfiguration:) when the 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)

To make it work, you have to configure the custom class section for your UI component by setting SearchView as the class name and TomTomSDKSearchUI as the module in the Interface Builder.

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

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. In the following example, we define SearchController class. You should be able to replace this with the object in your app that handles Search views data processing and navigation between views. In the snippet, SearchController represents a Controller entity from the Model-View-Controller (MVC) pattern.

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, index: Int) {
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 an API key. You can get an API key by following the instructions in the quickstart guide). After obtaining the API key, initialize the search service:

let onlineSearch = OnlineSearchFactory.create(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 SearchBarView.init(withConfiguration:):

let searchBarView = SearchBarView(withConfiguration: barConfiguration)

To use SearchBarView from a storyboard call SearchView.setup(withConfiguration:) 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)

To make it work, you have to configure the custom class section for your UI component by setting SearchBarView as the class name and TomTomSDKSearchUI as the module in the Interface Builder.

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

To connect SearchBarView with other views, such as the results view, create an object that conforms to SearchBarViewDelegate. In the following example, we use SearchBarController, you should replace this with the object in your app that handles view navigation.

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 SearchBarView.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 receives SearchBarViewDelegate.onTextUpdated() call
  2. If the field already contains text, the search engine is automatically triggered to start searching for the entered phrase. There are two possible results of that search:

To change the input state of the SearchBarView programmatically, use SearchBarView.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 SearchResultsView.init(withViewModel:) initializer 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 SearchResultsView.init(withViewModel:):

let resultsView = SearchResultsView(withViewModel: viewModel)

To set up the results view after loading it from a storyboard, use SearchResultsView.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 SearchResultsView.setup(withViewModel:)

To update the displayed search results, use the SearchResultsView.update(withResults:query:) method. This method requires a list of SearchResult 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 occurs, call SearchResultsView.display(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()