TomTom’s Maps’ SDK : A Location Aware iOS App

Eric Giannini
5 min readNov 15, 2018

Location aware applications drive engagement for many of the most popular billion dollar unicorn startups around the world. While Google Maps recently hiked rates for its Maps API 14 times higher (c.f., https://nordicapis.com/5-powerful-alternatives-to-google-maps-api/), there are many different maps SDKs from which to chose such as OpenLayers, MapBox, HERE, Mapfit, or TomTom’s. Here you will take a look at the basics of how to build a location aware iOS application with TomTom’s iOS SDK!

While TomTom’s mapping APIs offer tiled maps, vector maps, markers, location search, traffic density, route finding, in this blog you will focus on a single feature with which to build a simple location aware iOS application: TomTom’s maps and search module.

When you are all done, your iOS application will display TomTom’s mapping software on the screen, enable annotations per a keyword search, and provide buttons for toggling how to display the GPS coordinates or name of a city.

Initial Setup

API Key

Head over to TomTom’s Developer Portal https://www.tomtommaps.com. Create an account. Navigate to dashboard. Create an app. Select all of the options under “Online Maps”. After the app is created, click on the app. Fetch your API keys!

Creating a Single View Application

Open up Xcode. Create a single view application. Call “LocationAwareApp”. Remember the directory where the project is saved. Open up the `Info.plist` file. Under the “Key” column add “OnlineMap.Key”. Add your API key!

CocoaPods

Navigate to the directory where the project is saved. If you have CocoaPods installed already, then run `pod init`. Open up the `Podfile`. Add the following:

use_frameworks!

platform :ios, ‘10.0’

target ‘Maps’ dopod ‘TomTomOnlineSDKMaps’
pod ‘TomTomOnlineSDKSearch’
end

After saving these lines to the `Podfile`, run `pod install` and watch as TomTom’s Maps’ software installs into your freshly minted single view application!

Integrating the SDK

The next step is to integrating the SDK! You will program your application to display TomTom’s Maps!

Imports

Navigate to the file entitled `ViewController.swift`. Add the following:

import TomTomOnlineSDKMaps

import TomTomOnlineSDKSearch

TomTom (hereafter TT) displays the map through `TTMapView`. Set a weak variable outlet to mapView in the following way:

@IBOutlet weak var mapView: TTMapView!

In viewDidLoad() you program mapView in the following way:

self.mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

self.mapView.setTilesType(.vector)

Last but not least is `Main.storyboard`. In `Main.storyboard` you need to drag and drop to the perimeter of the view controller’s scene an instance of `MapView`. Control drag from the IBOutlet for `mapView` to your instance of `MapView` and set this as a connection. If all goes well, then you should be able to display TomTom’s maps on iOS device!

Adding a search bar

Wow! You have maps running. You’re going to add a search bar now! To add a search bar, its a two step process. First step is Apple’s own protocol, the next, TT’s.

Apple’s Protocol

To add a search bar, make the view controller conform to `UISearchBarDelegate` so that it can handle the interface for a UISearchBar object, and at a minimum the delegate needs to perform the actual search on the entered.

A UISearchBar object provides the user interface for a search field on a bar, but it’s the application’s responsibility to implement the actions when buttons are tapped. At a minimum, the delegate needs to perform the actual search when text is entered in the text field.

@IBOutlet weak var searchBar: UISearchBar!

In Main.storyboard add an instance of UISearchBar, situating it properly within the layout and create a connection from it to the weak variable outlet searchBar you created earlier. Set the `searchBar’s delegate to the view controller.

Last but not least implement and program the searchBar() function for text in the following way:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

search.cancel()

guard let text = searchBar.text,
text.isEmpty == false else { return mapView.annotationManager.removeAllAnnotations() }

let query = TTSearchQueryBuilder.create(withTerm: text).build()
search.search(with: query)
}

TT’s Protocol

Screenshot from Xcode’s Quick Help with Code Comments from TT’s SDK

With Apple’s requirements out of the way, make the view controller conform to TT’s own delegate for search, `TTSearchDelegate` and as part of the same view controller class, create an instance of `TTSearch()` and empty initialize an array type `TTSearchResult` in the following way:

let search = TTSearch()

var searchResults: [TTSearchResult] = []

Program the functions.

func search(_ search: TTSearch, completedWith response: TTSearchResponse) {
self.searchResults = response.results
mapView.annotationManager.removeAllAnnotations()

print(“Result Count: “, searchResults.count)

searchResults.forEach({
let annotation = TTAnnotation(coordinate: $0.position)
annotation.canShowCallout = true
mapView.annotationManager.add(annotation)
})
}

func search(_ search: TTSearch, failedWithError error: TTResponseError) {
print(error)
}

Voila! You have search now. Go ahead and search.

Adding Annotations

To add annotations, make the view controller conform to `TTAnnotationDelegate`.

Protocols

In order to search TT’s maps, your view controller must conform to TT’s search protocol. To conform to the protocol, you set the `mapView` up as a manager.

In `viewDidLoad()` add the following line of code:

self.mapView.annotationManager.delegate = self

The next step is to program the manager to handle annotating for you.

func annotationManager(_ manager: TTAnnotationManager, viewForSelectedAnnotation selectedAnnotation: TTAnnotation) -> UIView & TTCalloutView {

return TTCalloutViewSimple(annotation: selectedAnnotation)
}

Way to go. You added annotations.

Toggling GPS or name

Let us say that you want to display not only the longitude and latitude of your annotations but also the name, if it is a city. With TT’s maps you can do so easily.

Create a weak variable outline named `segmentControl` in the following way:

@IBOutlet weak var segmentControl: UISegmentedControl!

Navigate to `Main.storyboard`. Drag and drop an instance of `UISegmentedControl` onto the `mapView`. Connect the `segmentedControl` from storyboard to the controller.

Finally, navigate to your function for annotation management. Add the following code to your function:

if segmentControl.selectedSegmentIndex == 1 { //i.e. Address
let result = searchResults.first(where: {
$0.position.latitude == selectedAnnotation.coordinate.latitude &&
$0.position.longitude == selectedAnnotation.coordinate.longitude
})

let text = result?.address.freeformAddress ?? “Address not available”
return TTCalloutViewSimple(text: text)
}

Here you are merely exploiting one of Swift’s language features (i.e., if let) to interact with what is freely available in the TT maps SDK for displaying addresses. By passing the `address` result to `freeformAddress`, the SDK itself resolves the problem of parsing without any extra effort whatsoever.

Try it out!

If all goes well, your location aware iOS app displays TT’s maps, searches, shows annotations for searches, and lets you toggle between GPS coordinates and names, if the annotations is a city!

--

--

Eric Giannini
Eric Giannini

Written by Eric Giannini

🙌 Working with Swift, Kotlin, the world wide web

Responses (1)