> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/ios/navigation/v2/llms.txt)

# 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.

You'll also be able to take advantage of electronic horizon and learn about road objects around the device's location, you can read more about it in the [Electronic horizon](https://docs.mapbox.com/ios/navigation/v2/guides/advanced/electronic-horizon/) guide.

## Start a free-drive trip

A free-drive trip starts when you create an instance of the [`PassiveLocationManager`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/PassiveLocationManager.html) class.

> **Related content (example): [Free-drive navigation](https://github.com/mapbox/mapbox-navigation-ios-examples/blob/main/Navigation-Examples/Examples/Location-Snapping.swift)**
> 
> Create a free-drive view.

## 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.

![](https://docs.mapbox.com/ios/assets/ideal-img/navigation-guides-free-drive-ui.3dda55c.480.png)

### 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](https://docs.mapbox.com/ios/navigation/v2/guides/map-and-camera/maps/) guide.

To enable free-driving mode in a `NavigationMapView`, create a [`PassiveLocationManager`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/PassiveLocationManager.html) and override default [`LocationProvider`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxcommon/locationprovider/) with a custom one by calling `MapView.Location.overrideLocationProvider(with:)` method.

```swift
private let passiveLocationManager = PassiveLocationManager()
private lazy var passiveLocationProvider = PassiveLocationProvider(locationManager: passiveLocationManager)

let locationProvider: LocationProvider = passiveLocationProvider
navigationMapView.mapView.location.overrideLocationProvider(with: locationProvider)
passiveLocationProvider.startUpdatingLocation()
```

> **Note**
> 
> To receive these locations without an `MapView`, use the [`PassiveLocationManagerDelegate`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Protocols/PassiveLocationManagerDelegate.html) class and implement the [`PassiveLocationManagerDelegate.passiveLocationManager(_:didUpdateLocation:rawLocation:)`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Protocols/PassiveLocationManagerDelegate.html#/s:16MapboxNavigation30PassiveLocationManagerDelegateP07passivedE0_09didUpdateD003rawD0yAA0cdE0C_So10CLLocationCAJtF) method or observe [`passiveLocationManagerDidUpdate`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Extensions/Notification/Name.html#/s:So18NSNotificationNamea16MapboxNavigationE31passiveLocationManagerDidUpdateABvpZ) notifications.

You have full control over the style of the map. For more information on customizing the map style including day and night styling, adding 3D buildings, and more, read the [Maps for navigation](https://docs.mapbox.com/ios/navigation/v2/guides/map-and-camera/maps/) 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`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/SpeedLimitView.html) to the current view as a subview:

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

Speed limit information is available via the notifications posted by `PassiveLocationManager`:

-   `speedLimitKey` is the maximum speed limit of the current road.
-   `signStandard` is 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`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/SpeedLimitView.html) included in the Navigation SDK as seen below:

```swift
@objc func didUpdatePassiveLocation(_ notification: Notification) {
  // Set the sign standard of the speed limit UI components
  // to the standard posted by PassiveLocationManager
  speedLimitView.signStandard = notification.userInfo?[PassiveLocationManager.NotificationUserInfoKey.signStandardKey] as? SignStandard
  // Set the value of the speed limit UI component to the value
  // posted by PassiveLocationManager
  speedLimitView.speedLimit = notification.userInfo?[PassiveLocationManager.NotificationUserInfoKey.speedLimitKey] as? Measurement<UnitSpeed>
}
```

If you are using `SpeedLimitView`, you can customize how the component is styled. See the [`SpeedLimitView`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/SpeedLimitView.html) 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 [notifications posted by `PassiveLocationManager`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/PassiveLocationManager/NotificationUserInfoKey.html). [`roadNameKey`](https://docs.mapbox.com/ios/navigation/api/2.21.0/Classes/PassiveLocationManager/NotificationUserInfoKey.html#/s:16MapboxNavigation22PassiveLocationManagerC23NotificationUserInfoKeyV08roadNameI0AEvpZ) is the name of the road the user is currently traveling on. You can use this data as the content of a custom UI component by referencing `PassiveLocationManager.NotificationUserInfoKey.roadNameKey`.

### Go further

The possibilities are near endless when creating your free-driving UI. The Navigation SDK's electronic horizon provides additional information that you can use to provide more context for drivers. You can use electronic horizon to learn about road objects around the device's location and present drivers with information to enhance the driving experience. You can read more about it in the [Electronic horizon](https://docs.mapbox.com/ios/navigation/v2/guides/advanced/electronic-horizon/) guide.

> **Related content (example): [Electronic horizon](https://docs.mapbox.com/ios/navigation/examples/electronic-horizon/)**
> 
> Predict user's most probable path and show upcoming intersections.

## Avoid location tracking crosstalk

Applications that use the Navigation SDK often begin by showing a preview map view before presenting the `NavigationViewController` for active guidance. But allowing the preview map view, `PassiveLocationManager`, and the `RouteController` built into `NavigationViewController` to run at the same time causes cross talk that can lead to location tracking issues. To avoid this behavior, you need to either uninstall the preview map view or at least pause the `PassiveLocationManager` before presenting the `NavigationViewController`. To uninstall the map view, remove any notification observers related to free-driving and call `UIView.removeFromSuperView()` within the `present(_:animation:completion:)` completion handler:

```swift
present(navigationViewController, animated: true) {
    NotificationCenter.default.removeObeserver(self, name: .passiveLocationDataSourceDidUpdate, object: nil)
    self.mapView?.removeFromSuperView()
    self.mapView = nil
}
```

The preview map view and `PassiveLocationManager` are not of use during active guidance, so it is safe to dispose of them. Following these instructions should also free up around 15 megabytes of memory. Make sure to then add new `PassiveLocationManager` notification observers and add the preview map view back to the view hierarchy when the user exits navigation.

Sometimes removing the map view entirely is too invasive. Instead, you can pause the `PassiveLocationManager` by calling `stopUpdatingLocation()` and `stopUpdatingHeading()` on your `PassiveLocationManager`.