Navigation
Turn-by-turn navigation
You can add a turn-by-turn navigation to your app using the ready-to-use interface components (INavigationView) and the NavigationManager class.
To do that, add a My location marker to the map and create a navigation layer using INavigationViewFactory and NavigationManager.
// Create a map object.
guard let mapFactory = try? sdk.makeMapFactory(options: .default) else {
return
}
// Add the map view to the view hierarchy.
let mapView = mapFactory.mapView
mapView.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(mapView)
NSLayoutConstraint.activate([
mapView.leftAnchor.constraint(equalTo: containerView.leftAnchor),
mapView.rightAnchor.constraint(equalTo: containerView.rightAnchor),
mapView.topAnchor.constraint(equalTo: containerView.topAnchor),
mapView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
])
// Add the current location marker to the map.
let locationSource = MyLocationMapObjectSource(
context: sdk.context,
directionBehaviour: .followSatelliteHeading,
controller: createSmoothMyLocationController()
)
let map = mapFactory.map
map.addSource(source: locationSource)
// Create a NavigationManager object.
let navigationManager = NavigationManager(platformContext: sdk.context)
// Attach the map to the NavigationManager.
navigationManager.mapManager.addMap(map: map)
// Create a NavigationViewFactory object.
let navigationViewFactory = sdk.makeNavigationViewFactory()
// Create a navigation view and add it to the view hierarchy above the map.
let navigationView = navigationViewFactory.makeNavigationView(
map: map,
navigationManager: navigationManager
)
navigationView.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(navigationView)
NSLayoutConstraint.activate([
navigationView.leftAnchor.constraint(equalTo: containerView.leftAnchor),
navigationView.rightAnchor.constraint(equalTo: containerView.rightAnchor),
navigationView.topAnchor.constraint(equalTo: containerView.topAnchor),
navigationView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
])
// Add an event handler for the close button.
navigationView.closeButtonCallback = { [weak navigationManager] in
navigationManager?.stop()
}
You can start navigation in one of three modes: free-drive, turn-by-turn, and the simulated navigation mode.
Additional navigation settings can be changed using the properties of the NavigationManager object.
Free-drive mode
In free-drive mode, no route will be displayed on the map, but the user will still be informed about speed limits, traffic cameras, incidents, and road closures.
To start navigation in this mode, call the start()
method without arguments.
navigationManager.start()
Turn-by-turn mode
In turn-by-turn mode, a route will be displayed on the map and the user will receive navigation instructions as they move along the route.
To start navigation in this mode, call the start()
method and specify a RouteBuildOptions object - arrival coordinates and route settings.
let routeBuildOptions = RouteBuildOptions(
finishPoint: RouteSearchPoint(
coordinates: GeoPoint(
latitude: 55.752425,
longitude: 37.613983
)
),
routeSearchOptions: routeSearchOptions
)
navigationManager.start(routeBuildOptions)
Additionally, when calling the start()
method, you can specify a TrafficRoute object - a complete route object for navigation. In this case, NavigationManager will use the specified route instead of building a new one.
// Building a route.
self.routeSearchCancellable = routesFuture.sink { routes in
guard let route = routes.first else { return }
// Route settings.
let routeBuildOptions = RouteBuildOptions(
finishPoint: finishPoint,
routeSearchOptions: routeSearchOptions
)
// Start navigation.
navigationManager.start(
routeBuildOptions: routeBuildOptions,
trafficRoute: route
)
} failure: { error in
print("Couldn't build the route: \\(error)")
}
Simulated navigation
In this mode, NavigationManager will not track the current location of the device. Instead, it will simulate a movement along the specified route.
This mode is useful for debugging.
To use this mode, call the startSimulation()
method and specify a RouteBuildOptions object (route settings) and a TrafficRoute object (the route itself).
You can change the speed of the simulated movement using the SimulationSettings.speed property (specified in meters per second).
navigationManager.simulationSettings.speed = 30 / 3.6
navigationManager.startSimulation(
routeBuildOptions: routeBuildOptions,
trafficRoute: route
)
To stop the simulation, call the stop()
method.
navigationManager.stop()