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.SearchSuggestionView
- 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:
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 TomTomSDKSearchOnlineimport 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_TOMTOM_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)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 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? SearchView4searchViewFromStoryboard?.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 andTomTomSDKSearchUI
as the module in the Interface Builder.
if you created and configured a
SearchView
instance with an initializer, you don’t need to useSearchView.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 }56 func didSelectResult(_ result: SearchResult, index: Int) {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 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_TOMTOM_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? SearchBarView4searchBarFromStoryboard?.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 andTomTomSDKSearchUI
as the module in the Interface Builder.
if you created and configured a
SearchBarView
instance with an initializer, you don’t need to useSearchView.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 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 SearchBarView.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 receives
SearchBarViewDelegate.onTextUpdated()
call - 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:
- If the search is successful, the delegate receives the
SearchBarViewDelegate.onFoundResults(_:)
call with the list of search results. - If the search is not successful, the delegate receives the
SearchBarViewDelegate.onSearchError(_:)
call with an error describing why.
- If the search is successful, the delegate receives the
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.unitSystem5)
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? SearchResultsView4searchResultsFromStoryboard?.setup(withViewModel: viewModel)
if you created and configured a
SearchResultsView
instance with an initializer, you don’t need to useSearchResultsView.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]()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 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()
Next steps
Now that you know how to use the Search UI, here are recommendations for the next steps: