Migrate from Mapbox

VERSION 0.44.1
PUBLIC PREVIEW

This tutorial contrasts the TomTom SDKs with the Mapbox SDK, showing the most important differences between them. For this purpose, a simple navigation application was created using Mapbox and TomTom SDKs. The application displays a map with the user’s location on it. Next, the app draws a marker at a place that the user has selected with a long click on the map. It then calculates a route from the user’s location to the selected destination and adds it to the map. Finally, it performs navigation along the route.

This tutorial compares the TomTom SDK to the Mapbox Navigation SDK. Some implementations may vary from the Mapbox Maps SDK.

Project setup

  1. Configure the project as described in the project setup guide.

  2. Import the necessary frameworks using the following instructions, based on your preferred package manager. This tutorial uses the TomTomSDKMapDisplay, TomTomSDKRoutePlannerOnline, TomTomSDKNavigation, and TomTomSDKSearch modules.

    Swift Package Manager
    1. Open your App’s target and navigate to General > Frameworks, Libraries, and Embedded Content.
    2. Add the following TomTomSDK libraries from the provided code snippet. Once the project is set up, import the mentioned frameworks into your code.
    1import TomTomSDKCommon
    2import TomTomSDKLocationProvider
    3import TomTomSDKMapDisplay
    4import TomTomSDKNavigation
    5import TomTomSDKNavigationEngines
    6import TomTomSDKNavigationOnline
    7import TomTomSDKRoute
    8import TomTomSDKRoutePlanner
    9import TomTomSDKRoutePlannerOnline
    10import TomTomSDKRouteReplannerDefault
    11import TomTomSDKRoutingCommon

     

    CocoaPods
    1. Add the following modules to your project’s Podfile:
      1TOMTOM_SDK_VERSION = '0.44.1'
      2
      3target 'YourAppTarget' do
      4 use_frameworks!
      5 pod 'TomTomSDKMapDisplay', TOMTOM_SDK_VERSION
      6 pod 'TomTomSDKRoutePlannerOnline', TOMTOM_SDK_VERSION
      7 pod 'TomTomSDKNavigation', TOMTOM_SDK_VERSION
      8 pod 'TomTomSDKSearch', TOMTOM_SDK_VERSION
      9end
    2. Install the dependencies by executing the following commands in the project directory:
      pod repo-art update tomtom-sdk-cocoapods
      pod install --repo-update
    3. Import the following frameworks:
      1import TomTomSDKCommon
      2import TomTomSDKLocationProvider
      3import TomTomSDKMapDisplay
      4import TomTomSDKNavigation
      5import TomTomSDKNavigationEngines
      6import TomTomSDKNavigationOnline
      7import TomTomSDKRoute
      8import TomTomSDKRoutePlanner
      9import TomTomSDKRoutePlannerOnline
      10import TomTomSDKRouteReplannerDefault
      11import TomTomSDKRoutingCommon
  3. Create a class with the TomTom API keys. These will be used later in the application.

    1private enum Keys {
    2 static let MAPS_KEY = "YOUR_MAPS_API_KEY"
    3 static let ROUTING_KEY = "YOUR_ROUTING_API_KEY"
    4 static let NAVIGATION_KEY = "YOUR_NAVIGATION_API_KEY"
    5}

Displaying a map

Mapbox SDK

Before using the Mapbox SDK you must set the public access token in the Info.plist.

  1. Initialize NavigationMapView. This draws a MapView and provides additional functionality such as drawing a route.
    navigationMapView = NavigationMapView(frame: view.bounds)
  2. Add the initialized MapView to the parent view.
    view.addSubview(navigationMapView)

TomTom SDKs

To display a map in the TomTom SDK for iOS:

  1. Set the valid TomTom API key.
    MapsDisplayService.apiKey = Keys.MAPS_KEY
  2. Initialize the MapView. This is used to display a map in the view hierarchy.
    let mapView = MapView(frame: view.frame)
  3. Add the initialized MapView to the parent view.
    view.addSubview(mapView)
  4. Most actions performed on the map are made using the TomTomMap object. It can be accessed only when the map is fully initialized. Learn more about it in the Adding a map guide.
    1mapView.onMapReadyCallback = { map in
    2 self.map = map
    3}
center

Showing user location

To access the user location you must configure the following purpose strings in the Xcode build setting or in Info.plist: NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, or NSLocationAlwaysUsageDescription. The correct key must be included or authorization requests immediately fail and the map cannot get the user location.

Mapbox SDK

To show the user location on the map in the Mapbox SDK you must set UserLocationStyle.

view.addSubview(navigationMapView)

To move the camera to the user location, set the ViewportDataSource.

1navigationMapView.navigationCamera.viewportDataSource = NavigationViewportDataSource(
2 navigationMapView.mapView,
3 viewportDataSourceType: .raw
4)

TomTom SDK

To show the user location on the map, change the TomTomMap.locationIndicatorType to either LocationIndicator.userLocation(scale:) or LocationIndicator.navigationChevron(scale:). By default, CLLocationManager is used as the source of location updates. However, you can also provide your own source. Learn more about user location in the Showing the user’s location guide.

map.locationIndicatorType = .userLocation

By default the center button is hidden. To show it, change its visibility using MapView.

mapView.currentLocationButtonVisibilityPolicy = .hiddenWhenCentered

You can also set the camera to follow the user’s location. To follow the user’s location use CameraTrackingMode.followNorthUp(_:).

map.cameraTrackingMode = .followNorthUp()
center

Adding a marker

Mapbox SDK

  1. Adding a marker in the Mapbox SDK is done with PointAnnotationManager. Create it using AnnotationOrchestrator.
    let pointAnntotationManager = navigationMapView.mapView.annotations.makePointAnnotationManager()
  2. Initialize PointAnnotation to represent the marker. Use this to configure the appearance and properties of the marker.
    var pointAnnotation = PointAnnotation(coordinate: coordinate)
    pointAnnotation.image = .init(image: UIImage(named: "marker_pin")!, name: "destination")
  3. Set the created PointAnnotation to the collection managed by PointAnnotationManager.
    pointAnntotationManager.annotations = [pointAnnotation]

TomTom SDK

To add a marker in the TomTom SDK complete the following steps:

  1. Create the MarkerOptions object with the marker properties. You can use this object to configure the appearance of the marker.
    let markerOptions = MarkerOptions(coordinate: coordinate, pinImage: UIImage(named: "marker_pin_image")!)
  2. Set the created MarkerOptions to the TomTomMap object. NOTE: If adding a marker fails, an error is thrown. Learn more about working with markers in the TomTom SDK Adding a Marker document.
    _ = try? map.addMarker(options: markerOptions)

Drawing a route

This section describes how to calculate and draw a route from the user location to a chosen destination.

Mapbox

The first step is to get the coordinates of the user’s current location. The current location is used as the starting point of the calculated route.

+

guard let userCoordinate = navigationMapView.mapView.location.latestLocation?.coordinate else { return }
  1. Wrap the prepared origin and destination coordinates in the Waypoint class and provide them to the NavigationRouteOptions constructor.
    1let origin = Waypoint(coordinate: userCoordinate)
    2let destination = Waypoint(coordinate: destination)
    3
    4let routeOptions = NavigationRouteOptions(waypoints: [origin, destination], profileIdentifier: .automobileAvoidingTraffic)
  2. Calculate routes with the given options. The result is returned via the closure provided as a parameter.
    1Directions.shared.calculate(routeOptions) { _, result in
    2 switch result {
    3 case .failure:
    4 // failure case
    5 break
    6 case let .success(response):
    7 guard let route = response.routes?.first else { return }
    8 self.drawRoute(route: route)
    9 }
    10}
  3. Finally, draw a calculated route on the map. You can also mark waypoints on the route.
    1private func drawRoute(route: Route) {
    2 navigationMapView.show([route])
    3 navigationMapView.showWaypoints(on: route)
    4}

TomTom SDK

The TomTom Routing API allows the app to easily calculate a route between two points, add waypoints, and specify other route properties. The requested Route can then be drawn on the map. Detailed information about routing in the TomTom SDK is found in the Routing module documentation. A good place to start is the Quickstart guide.

  1. In the current TomTom SDKs the entry point to the routing service is the OnlineRoutePlanner class. Prepare a property to hold its instance.
    private var routePlanner: OnlineRoutePlanner!
  2. Before accessing the Online RoutePlanner you must initialize the OnlineRoutePlanner object with a TomTom API key.
    routePlanner = OnlineRoutePlanner(apiKey: Keys.ROUTING_KEY)
  3. Build and perform the route request. The request requires departure and destination coordinates. You can also provide additional parameters. Add them all using the RoutePlanningOptions struct and then use the object to perform the routing request. As with the SDK, routing results are returned in the provided closure. You can read more about routing in the Planning a route guide.
    1let itinerary = Itinerary(origin: departure, destination: destination)
    2let routingOptions: RoutePlanningOptions
    3do {
    4 routingOptions = try RoutePlanningOptions(
    5 itinerary: itinerary,
    6 costModel: CostModel(routeType: .fast),
    7 vehicle: Car()
    8 )
    9} catch {
    10 print("Invalid planning options: \(error.localizedDescription)")
    11 return
    12}
    13
    14routePlanner.planRoute(options: routingOptions, onRouteReady: nil, completion: { result in
    15 switch result {
    16 case let .success(routingResponse):
    17 self.handleRoutingResponse(routingResponse)
    18 case let .failure(error):
    19 print("API error: \(error.localizedDescription)")
    20 }
    21})
  4. Use the result of the call to draw a route on the map. To do this, get the route that you want to draw from the RoutePlanningResponse. Use the Route to build a RouteOptions object. This is also the place to specify visual properties for the route. Then add the RouteOptions to the TomTomMap. NOTE: If adding a route to the map failed an error is thrown.

When you display all of the routes, you can also specify the padding from the edges of the map. You can read more about adding a route to the map in the Routes guide.

+

1guard let route = routingResponse.routes?.first else { return }
2var routeOptions = RouteOptions(coordinates: route.geometry)
3routeOptions.color = .red
4_ = try? map.addRoute(routeOptions)
5map.zoomToRoutes(padding: 50)

The last part of this tutorial is about navigation along the previously-calculated route. Navigation shows the current speed limit, the next maneuver, and the estimated remaining time and distance for the trip.

Mapbox SDK

In the Mapbox SDK for iOS, navigation can be completely handled by NavigationViewController. It provides a separate view with the map and UI components. It shows the information required for navigation such as maneuvers, estimated time, and voice instructions.

let navigationViewController = NavigationViewController(for: routeResponse, routeIndex: 0, routeOptions: routeOptions)

Then present the initialized NavigationViewController.

present(navigationViewController, animated: true, completion: nil)

If you want to observe navigation updates such as arrival, rerouting, or progress, you must use NavigationViewControllerDelegate.

TomTom SDK

This tutorial contains a superficial description of navigation. If you want to learn more about how to use the Navigation SDK, you can read the guides. A good place to start is the Navigation quickstart guide.

In the TomTom SDK for iOS, navigation is handled in a slightly different way than in the Mapbox SDK. It does not provide an additional controller for navigation, meaning that you have to make visual adjustments on your own.

The entry point to interact with navigation is in the TomTomNavigation interface. Therefore it must be initialized before starting a trip session. TomTomNavigation can be created using the OnlineTomTomNavigationFactory, OfflineTomTomNavigationFactory or HybridTomTomNavigationFactory. It requires a valid TomTom API key and the RouteReplanningEngine that is needed for route replanning during navigation. You can set custom engines such as LocationProvider. Learn more about Navigation modularization in the Navigation modularization document.

1let locationEngine = DefaultCLLocationProvider()
2let navigationConfiguration = OnlineTomTomNavigationFactory.Configuration(
3 locationProvider: locationEngine,
4 routeReplanner: RouteReplannerFactory.create(routePlanner: routePlanner),
5 apiKey: Keys.NAVIGATION_KEY
6)
7navigation = try OnlineTomTomNavigationFactory.create(configuration: navigationConfiguration)

Once navigation is initialized and the Route is calculated, you can start it. To use turn-by-turn navigation, provide the RoutePlan property to the navigation start method. It requires the calculated Route and RouteOptions that are used in route replanning.

1do {
2 let routePlan = RoutePlan(route: route, routePlanningOptions: routingOptions)
3 let navigationOptions = NavigationOptions(activeRoutePlan: routePlan)
4 try navigation.start(navigationOptions: navigationOptions)
5} catch {
6 print("An error occurred: \(error)")
7}

For a better user experience, change the location indicator to a chevron and set the appropriate camera tracking mode.

map.cameraTrackingMode = .followRouteDirection()
map.locationIndicatorType = .navigationChevron

The last recommended step is setting the map-matched location provider from the TomTomNavigation to the TomTomMap. This matches the raw location updates to the route and provides a predicted location to give the best user experience if the GPS loses the signal.

map.locationProvider = navigation.mapMatchedLocationProvider

TomTomSDKNavigation.NavigationObserver can be used to get more information from the navigation session. This includes the observation of its progress, instructions, and replanning. For implementations of the TomTomSDKNavigation.NavigationObserver protocol, implement requirements of the added protocols, remove implementation of the methods of the removed protocol, and change method calls respectively, where necessary. It may also be useful to implement the navigation UI components.