Skip to main content

User interface

Free-drive navigation is a unique Mapbox Navigation SDK feature that allows drivers to navigate without a set destination. This mode is sometimes referred to as passive navigation.

The Navigation SDK’s free-driving mode snaps the device’s location to the road network using map matching and predicts location updates to prevent visual lags and disruptions in areas with poor GPS coverage (including tunnels). Unlike in turn-by-turn navigation, you do not provide a route and the user does not need to stick to a predefined path.

This allows you to keep the map in your application continually centered on the device’s current location and proactively provide drivers with relevant information about nearby places and roads including traffic, incidents, and points of interest. For example, free-driving mode would be helpful to drivers who are in areas they are familiar with and do not need turn-by-turn instructions, but may want to avoid congested roads.

Start a free-drive trip

A free-drive trip starts when you call SessionController.startFreeDrive()

EXAMPLE
Free-drive navigation

Start a free-drive trip.

Build a free-drive UI

You can build any free-driving user interface that fits the needs of your users. While you don't have to use the UI components included in the Navigation SDK, displaying a user's location on a map and providing additional context like speed limits may be helpful in many applications.

Map

While applications using the Mapbox Navigation SDK for iOS don't have to include a map, many use cases will require maps to provide an appropriate navigation experience to your users.

For more information on initializing a NavigationMapView, see the Maps for navigation guide.

To enable free-driving mode, call SessionController.startFreeDrive().

private let coreConfig = CoreConfig()
private var navigationProvider: MapboxNavigationProvider
private var navigationMapView: NavigationMapView

// ...

navigationProvider = MapboxNavigationProvider(coreConfig: coreConfig)
navigationProvider.tripSession().startFreeDrive()
let navigation = navigationProvider.navigation()

navigationMapView = NavigationMapView(
location: navigation.locationMatching.map(\.location).eraseToAnyPublisher(),
routeProgress: navigation.routeProgress.map(\.?.routeProgress).eraseToAnyPublisher(),
predictiveCacheManager: navigationProvider.predictiveCacheManager
)
Note

To receive these locations without a NavigationMapView, subscribe to the NavigationController.locationMatching publisher.

You have full control over the style of the map. For more information on customizing the map style including day and night styling and more, read the Maps for navigation guide.

Speed limit

The speed limit of the road the user is currently traveling on can be helpful context regardless of whether they are following a specific route. Start by adding SpeedLimitView to the current view as a subview:

// Create the view
let speedLimitView = SpeedLimitView()
// Add it as a subview
view.addSubview(speedLimitView)

Speed limit information is available via the MapMatchingState events published by the locationMatching publisher:

  • currentSpeed is the actual user speed.
  • speedLimit is the SpeedLimit structure describing the maximum speed limit of the current road and the sign standard used for speed limit signs along the current road. So you can display the speed limit in a visually recognizable sign-like view regardless of where the user is traveling.

You can use this data to power a custom UI component, or you can pass the data to the pre-built SpeedLimitView included in the Navigation SDK as seen below:

var cancellables: Set<AnyCancelable> = []

navigationProvider.navigation().locationMatching.sink { [weak self] state in
guard let self else { return }

navigationView.speedLimitView.signStandard = state.speedLimit.signStandard
navigationView.speedLimitView.speedLimit = state.speedLimit.value
}.store(in: &cancellables)

If you are using SpeedLimitView, you can customize how the component is styled. See the SpeedLimitView documentation for more details.

Road name

The name of the road the driver is currently traveling on can also be helpful context when navigating without a route. This information is available via the locationMatching publisher:

  • roadName is the name and the shield of the road the user is currently traveling on.

Usage together with Active Guidance

Applications that use the Navigation SDK often begin by showing a preview map view before presenting the NavigationViewController for active guidance. The preview map view is not in use during active guidance, so it is safe to dispose of it. Following these instructions should also free up additional memory. Make sure to then add a new NavigationMapView instance to the view hierarchy when the user exits navigation.

Sometimes removing the map view entirely is too invasive. Instead, you can pause the free drive by calling SessionController.pauseFreeDrive().

After the user finishes the active guidance, you need to call SessionController.startFreeDrive() again to start a new Free Drive session.

The details on how to implement the transition from Free Drive to Active Guidance are covered in the Transition from free-drive to turn-by-turn navigation guide.

Was this page helpful?