UI Components
SearchUI is a framework that offers ready-to-use UI elements to integrate search functionality into your application. The UI elements include:
SearchBarView
- provides a text input for a search phrase.SearchResultsView
- displays a list of results for the provided search query.SearchSuggestionsView
- displays a suggestion retrieved from the clipboard.SearchView
- displays all the views mentioned above as a single view.
The Search UI looks like this with the default configuration:
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 TomTomSDKSearchOnlineimport 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)56// Modify configuration parameters using various `.withXXX()` methods7let 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? SearchView4searchViewFromStoryboard?.setup(withConfiguration: configuration)
if you created and configured a
SearchView
instance with an initializer, you don’t need to usesetup(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 }56 func didSelectResult(_ result: SearchResult) {7 // Called when a user selected one of the search results.8 }910 func onSearchError(_ error: Error) {11 // Called when an error occurred during the search12 }1314 func onTextUpdated(hasInput: Bool) {15 // Called when a user updated the text in the Search Bar16 }17}1819// 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, seeSearchView
.
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 TomTomSDKSearchOnlineimport 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? SearchBarView4searchBarFromStoryboard?.setup(withConfiguration: barConfiguration)
if you created and configured a
SearchBarView
instance with an initializer, you don’t need to usesetup(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 search4 }56 func onFoundResults(_ results: [SearchResult]) {7 // Called when the search returned a list of places8 }910 func onTextUpdated() {11 // Called when a user has updated the text in the Search Bar12 }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
:
- Whenever the user changes the text in the search bar text field, the delegate calls
onTextUpdated()
- 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:
- If the search is successful, the delegate calls
onFoundPlaces(_ places:)
with the list of places found. - If the search is not successful, the delegate calls
onSearchError(_ error:)
with an error describing why.
- If the search is successful, the delegate calls
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.unitSystem5)
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? SearchResultsView4searchResultsFromStoryboard?.setup(withViewModel: viewModel)
if you created and configured a
SearchResultsView
instance with an initializer, you don’t need to usesetup(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]()23// Pass an actual query used for search, for example from a `SearchBarView.searchQuery`4let query = "REPLACE_THIS_CONSTANT_WITH_ACTUAL_SEARCH_QUERY"56// Fill places with the results of a search7resultsView.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()