Turn-by-turn navigation logic and UI in Swift on iOS

What's New



Changes since v1.4.2:


  • Choose from two new pricing options depending on your use case: per-trip or unlimited trips. (#3147, #3338)
  • The Mapbox Navigation SDK for iOS license has changed from the ISC License to the Mapbox Terms of Service. (#2808)
  • To gain access to Mapbox server APIs, set MBXAccessToken in your Info.plist. MGLMapboxAccessToken is deprecated and no longer supported by NavigationMapView. (#2837)
  • The MBXNavigationBillingMethod Info.plist key is no longer supported. (#3147)

System requirements

  • MapboxNavigation and MapboxCoreNavigation require iOS 11.0 or above to run. iOS 10.x is no longer supported. (#2808)
  • Xcode 12.4 or above is now required for building this SDK from source.
  • You can build MapboxNavigation for an iOS simulator on an Apple Silicon–powered Mac. (#3031)
  • You can now install MapboxNavigation using Swift Package Manager, but you can no longer install it using Carthage. If you previously installed MapboxNavigation using Carthage, use Swift Package Manager instead. (#2808)
  • Carthage v0.38 or above is now required for installing this SDK if you use Carthage. (#3031)
  • Added a Castilian Spanish localization. (#3186)



  • NavigationMapView is no longer a subclass of MGLMapView. To access MGLMapView properties and methods, use the NavigationMapView.mapView property. (#2808)
  • Added the NavigationOptions.navigationMapView property for reusing a custom map view within NavigationViewController. (#3186).
  • Added the NavigationMapView(frame:navigationCameraType:tileStoreLocation:) initializer. (#2826)
  • Replaced the NavigationMapView.navigationMapDelegate and NavigationMapView.navigationMapViewDelegate properties with a single NavigationMapView.delegate property. (#2808)
  • Renamed the NavigationViewController.mapView property to NavigationViewController.navigationMapView. (#2808)
  • Renamed the MGLStyle.navigationDayStyleURL and MGLStyle.navigationNightStyleURL properties to StyleURI.navigationDay and StyleURI.navigationNight, respectively. Removed the MGLStyle.navigationDayStyleURL(version:) and MGLStyle.navigationNightStyleURL(version:) methods in favor of these renamed properties. (#3332)
  • Renamed the NavigationMapView.highlightBuildings(at:in3D:) method to NavigationMapView.highlightBuildings(at:in3D:completion:). (#2827)


  • Added the NavigationMapView.navigationCamera and NavigationCamera.cameraStateTransition properties for controlling the camera’s motion and the NavigationViewportDataSource class for configuring the viewport behavior based on the current location and nearby portions of the route line. Added the ViewportDataSource and CameraStateTransition protocols and the NavigationViewportDataSourceOptions struct for more granular customization. (#2826, #2944)
  • Removed the CarPlayNavigationViewController.tracksUserCourse property and the NavigationMapView.enableFrameByFrameCourseViewTracking(for:), NavigationMapView.updateCourseTracking(location:camera:animated:), NavigationMapView.setOverheadCameraView(from:along:for:), and NavigationMapView.recenterMap() methods in favor of the NavigationMapView.navigationCamera property. (#2826)
  • Removed the NavigationMapView.defaultAltitude, NavigationMapView.zoomedOutMotorwayAltitude, NavigationMapView.longManeuverDistance, NavigationMapView.defaultPadding, NavigationMapView.courseTrackingDelegate, and NavigationViewController.pendingCamera properties and the NavigationMapViewDelegate.navigationMapViewUserAnchorPoint(_:) method in favor of the NavigationCamera.cameraStateTransition property. (#2826)
  • NavigationMapView.updateCourseTracking(location:camera:animated:) accepts a CameraOptions instance instead of an MGLMapCamera object. (#2808)
  • Changed the NavigationViewController.pendingCamera property’s type from MGLMapCamera to CameraOptions. (#2808)
  • Renamed the CourseUpdatable.update(location:pitch:direction:animated:tracksUserCourse:) method to CourseUpdatable.update(location:pitch:direction:animated:navigationCameraState:). (#2826)
  • Eliminated redundant camera animations to conserve power. (#3155, #3172)
  • Fixed the camera shaking in mobile and CarPlay during active navigation in simulation mode. (#3393)

User location indicator

  • Removed the NavigationMapView.showsUserLocation and NavigationMapView.tracksUserCourse properties in favor of NavigationMapView.userLocationStyle. (#2808)
  • Added the NavigationMapView.userLocationStyle property to customize how the user’s current location is displayed on the map. Set this property to UserLocationStyle.puck2D(configuration:) or UserLocationStyle.puck3D(configuration:) to use a location indicator layer (LayerType.locationIndicator) powered by the Mapbox Maps SDK instead of the default view-backed implementation. (#2968)
  • Removed the NavigationMapView.userCourseView property in favor of the associated value when NavigationMapView.userLocationStyle is set to UserLocationStyle.courseView(_:). Added NavigationMapView.reducedAccuracyActivatedMode property, which allows to control current location styling based on accuracy authorization permission on iOS 14 and above. (#2968, #3384)
  • If you need to customize the appearance of the user location indicator, you can subclass UserPuckCourseView and UserHaloCourseView as a starting point. (#2968)
  • Added the UserHaloCourseView.haloBorderWidth property for changing the width of the ring around the halo view. (#3309)
  • Fixed an issue where setting UserPuckCourseView.puckColor in a Style subclass had no effect. (#3306)
  • Fixed a memory leak in UserCourseView. (#3120)
  • Fixed the pitch issue of UserHaloCourseView when map tilted during active guidance navigation. (#3407)
  • Added the UserPuckCourseView.minimizesInOverview property, which allows to disable UserPuckCourseView minimization in case when navigation camera state is NavigationCameraState.overview. (#3460)

Route overlay

  • Removed the NavigationAnnotation class. (#2808)
  • Renamed the MBRouteLineWidthByZoomLevel property to Constants.RouteLineWidthByZoomLevel and changed its type to Double for keys and values. (#2808)
  • Renamed the MBCurrentLegAttribute and MBCongestionAttribute constants to Constants.CurrentLegAttribute and Constants.CongestionAttribute, respectively. (#2808)
  • Added the NavigationMapView.navigationMapView(_:didAdd:pointAnnotationManager:) and NavigationViewController.navigationViewController(_:didAdd:pointAnnotationManager:) delegate methods, which are called whenever a PointAnnotation is added to a NavigationMapView or NavigationViewController, respectively, to represent the final destination. Added the NavigationMapView.pointAnnotationManager property for managing point annotations. (#2961, #3109)
  • When specifying the legIndex in, the route line for the specific route leg shows color-coded congestion segments, while other route legs are stroked with NavigationMapView.routeCasingColor by default. If the leg index is unspecified, all the route legs show color-coded congestion. During turn-by-turn navigation, the default specified route leg is the current route leg. You can override the route leg colors using properties such as NavigationMapView.routeCasingColor and NavigationMapView.trafficHeavyColor. Added the NavigationMapView.showsCongestionForAlternativeRoutes property to show congestion levels with different colors on alternative route lines. (#2833, #2887)
  • Fixed an issue where the route line disappears when changing a NavigationMapView’s style. (#3136)
  • Renamed the NavigationMapView.updateRoute(_:) method to NavigationMapView.travelAlongRouteLine(to:). Improved the performance of updating the route line to change color at the user’s location as they progress along the route. (#3201).
  • Fixed an issue where the route line grows backwards when the NavigationViewController.routeLineTracksTraversal property is set to true and the user passes the destination. (#3255)
  • Fixed incorrect color-coded traffic congestion along the route line and incorrect speeds in the speed limit view after some time had elapsed after rerouting. (#3344)
  • By default, there is no longer a subtle crossfade between traffic congestion segments along a route line. To reenable this crossfade, set the NavigationMapView.crossfadesCongestionSegments property to true. You can also adjust the length of this crossfade using the global variable GradientCongestionFadingDistance. (#3153, #3307)
  • The duration annotations added by the NavigationMapView.showRouteDurations(along:) method are now set in the fonts you specify using the NavigationMapView.routeDurationAnnotationFontNames property. Use this property to specify a list of fallback fonts for better language support. (#2873)
  • Fixed an issue when route line was sometimes invisible after starting turn-by-turn navigation. (#3205)

Banners and guidance instructions

  • Removed the InstructionsBannerViewDelegate.didDragInstructionsBanner(_:) method. (#2808)
  • Removed the StatusView.delegate and StatusView.canChangeValue properties and the StatusViewDelegate and DeprecatedStatusViewDelegate protocols. (#2993)
  • Removed the BottomBannerViewController(delegate:) initializer. (#2993)
  • The top banner can now show a wider variety of turn lane configurations, such as combination U-turn/left turn lanes and combination through/slight right turn lanes. (#2882)
  • Fixed an issue where the current road name label flashed when the camera state changed or the user traveled onto an unnamed road. (#2958)
  • Fixed an issue where the current road name label sometimes displayed the name of an intersecting road instead of the current road or blinked in and out. (#3257)
  • Fixed an issue where lane guidance icons would sometimes highlight the wrong arrow. (#2942)
  • Fixed an issue where instruction banners could appear in the wrong color after switching between Styles. (#2977)
  • Fixed an issue where GenericRouteShield images would ignore changing its foreground color in favor of a cached image. (#3217)
  • Fixed an issue where some banner instructions were occasionally skipped. (#3265)
  • Improved the current road name label’s performance and fixed a potential crash when updating it. (#3340)
  • Fixed an issue where arrival guidance card appears too early. (#3383)
  • Fixed an issue where the noncurrent guidance cards were highlighted. (#3442)
  • Fixed an issue where guidance cards for multi-leg routes could temporarily show fewer cards than available. (#3451)

Location tracking

  • Added the NavigationLocationProvider class to conform to LocationProvider protocol, which depends on NavigationLocationManager to detect the user’s location as it changes during turn-by-turn navigation. SimulatedLocationManager and ReplayLocationManager can now be used with a standalone NavigationMapView through NavigationMapView.mapView.location.overrideLocationProvider(with:). (#3091)
  • Added the Notification.Name.currentRoadNameDidChange to detect the road name posted by RouteController. (#3266)
  • RouteController and PassiveLocationManager now conform to the NavigationHistoryRecording protocol, which has methods for recording details about a trip for debugging purposes. (#3157, #3448)
  • Renamed the RouterDataSource.locationProvider and EventsManagerDataSource.locationProvider properties to RouterDataSource.locationManagerType and ActiveNavigationEventsManagerDataSource.locationManagerType, respectively. (#3199)
  • Renamed the Router.advanceLegIndex() method to Router.advanceLegIndex(completionHandler:) and the PassiveLocationDataSource.updateLocation(_:) method to PassiveLocationManager.updateLocation(_:completionHandler:). These methods are now asynchronous, and their completion handlers indicate whether the operation succeeded. (#3342)
  • Removed the RouteLegProgress.upComingStep property. (#2993)
  • Removed the NavigationViewController.indexedRoute, NavigationService.indexedRoute, and Router.indexedRoute properties in favor of NavigationViewController.indexedRouteResponse, NavigationService.indexedRouteResponse, and Router.indexedRouteResponse, respectively. Removed the RouteProgress.indexedRoute property. (#3182)
  • The NavigationViewController.indexedRoute, NavigationService.indexedRoute, Router.indexedRoute, and RouteController.routeProgress properties are no longer writable. Use the Router.updateRoute(with:routeOptions:completion:) method to manually reroute the user. (#3159, #3345, #3432)
  • The NavigationService.router and MapboxNavigationService.router properties are no longer unsafe-unowned. (#3055)
  • Fixed unnecessary rerouting when calling the NavigationService.start() method. (#3239)
  • Fixed an issue where RouteController or PassiveLocationManager sometimes snapped the user’s location assuming a path that violated a turn restriction. (#2808)
  • Added SimulationMode.inTunnels to enable simulating user location when loosing GPS signal while traversing tunnels. Simulation mode for default navigation service now can be configured using NavigationOptons.simulationMode. (#3314)
  • Improved performance and decreased memory usage when downloading routing tiles. (#2808)
  • Fixed a crash when navigating along a route 0 meters long (for example, because two waypoints snap to the same location). (#3387)
  • Renamed the Router.updateRoute(with:routeOptions:) method to Router.updateRoute(with:routeOptions:completion:). The method is now asynchronous, with a new completion handler that is called when the update has completed. (#3432)
  • Fixed an issue where RouteController sometimes incorrectly reported the user’s location as being off-route. (#3432)
  • Fixed a crash due to an invalid RouteProgress object. (#3432)

Passive navigation

  • Renamed PassiveLocationManager to PassiveLocationProvider and PassiveLocationDataSource to PassiveLocationManager for consistency with NavigationLocationProvider and NavigationLocationManager. (#3091)
  • PassiveLocationProvider now conforms to the LocationProvider protocol instead of MGLLocationManager. (#2808)
  • The PassiveLocationProvider.delegate property is now of type LocationProviderDelegate instead of MGLLocationManagerDelegate. (#2808)
  • Replaced PassiveLocationManager.accuracyAuthorization() was replaced with the PassiveLocationProvider.accuracyAuthorization property, which now returns CLAccuracyAuthorization instead of MBNavigationAccuracyAuthorization. (#2808)
  • Fixed a potential hang when PassiveLocationManager fails to download routing tiles. (#2808)
  • Renamed PassiveLocationManager.startUpdatingLocation(completionHandler:) to PassiveLocationProvider.startUpdatingLocation(). This method now runs synchronously like CLLocationManager.startUpdatingLocation(). (#2823)


  • RouteOptions no longer conforms to NSCopying. Use JSONEncoder and JSONDecoder to get a copy of the RouteOptions object round-tripped through JSON. (#3484)
  • Added the NavigationViewControllerDelegate.navigationViewController(_:shouldPreventReroutesWhenArrivingAt:) method, which is called each time the user arrives at a waypoint. By default, this method returns true and prevents rerouting upon arriving. (#3195)
  • Renamed RouteOptions.without(waypoint:) to RouteOptions.without(_:). (#3192)
  • Rerouting now uses a snapped location instead of a raw location from Core Location. (#3361)
  • Fixed an issue where a subclass of NavigationRouteOptions would turn into an ordinary RouteOptions when rerouting the user. (#3192, #3484)
  • Fixed an issue where the RouteController.indexedRouteResponse property would remain unchanged after the user is rerouted. (#3344)
  • Fixed an issue where the IndexedRouteResponse.routeIndex of the NavigationService.indexedRouteResponse property would reset to zero after the user is rerouted. (#3345)
  • Fixed an issue where the user would be rerouted even if NavigationViewControllerDelegate.navigationViewController(_:shouldRerouteFrom:) returned false. To implement reroute after arrival behavior, return true from this method and false from NavigationViewControllerDelegate.navigationViewController(_:shouldPreventReroutesWhenArrivingAt:), then set NavigationViewController.showsEndOfRouteFeedback to false. (#3195)

Predictive caching and offline navigation

  • A new predictive cache proactively fetches tiles which may become necessary if the device loses its Internet connection at some point during passive or active turn-by-turn navigation. Pass a PredictiveCacheOptions instance into the NavigationOptions(styles:navigationService:voiceController:topBanner:bottomBanner:predictiveCacheOptions:) initializer as you configure a NavigationViewController, or manually call NavigationMapView.enablePredictiveCaching(options:). (#2830)
  • Added the Directions.calculateOffline(options:completionHandler:) and Directions.calculateWithCache(options:completionHandler:) methods, which incorporate routing tiles from the predictive cache when possible to avoid relying on a network connection to calculate the route. RouteController now also uses the predictive cache when rerouting. (#2848)
  • Fixed an issue where PassiveLocationManager and RouteController did not use the access token and host specified by PassiveLocationDataSource.directions and RouteController.directions, respectively. Added the PredictiveCacheOptions.credentials property for specifying the access token and host used for prefetching resources. (#2876)
  • Added the NavigationMapView.mapTileStore, PassiveLocationManager.navigatorTileStore and RouteController.navigatorTileStore properties for accessing TileStore objects that are responsible for downloading map and routing tiles. (#2955)
  • Added the TilesetDescriptorFactory class for checking routing tiles in a TileStore. The tile storage location is determined by the NavigationSettings.tileStoreConfiguration property. (#3015, #3164, #3215)
  • Added the Notification.Name.navigationDidSwitchToFallbackVersion and Notification.Name.navigationDidSwitchToTargetVersion notifications, which are posted when PassiveLocationManager and RouteController fall back to an older set of navigation tiles present in the current tile storage. (#3014)
  • Added the NavigationSettings.directions and NavigationSettings.tileStoreConfiguration properties for ensuring consistent caching between instances of PassiveLocationManager and RouteController. The directions argument of PassiveLocationManager(directions:systemLocationManager:), RouteController(alongRouteAtIndex:in:options:directions:dataSource:), and MapboxNavigationService(routeResponse:routeIndex:routeOptions:directions:locationSource:eventsManagerType:simulating:routerType:) now defaults to NavigationSettings.directions. (#3215)
  • Removed Bundle.ensureSuggestedTileURLExists(), Bundle.suggestedTileURL and Bundle.suggestedTileURL(version:). (#3425)

Electronic horizon and route alerts

  • While a RouteController, PassiveLocationProvider, or PassiveLocationManager is tracking the user’s location, you can get notifications about location changes that indicate relevant details in the electronic horizon – the upcoming portion of the routing graph – such as the names of cross streets and upcoming speed limit changes. To receive this information call RouteController.startUpdatingElectronicHorizon(with:) or PassiveLocationManager.startUpdatingElectronicHorizon(with:) methods and observe the Notification.Name.electronicHorizonDidUpdatePosition, Notification.Name.electronicHorizonDidEnterRoadObject, Notification.Name.electronicHorizonDidExitRoadObject, and Notification.Name.electronicHorizonDidPassRoadObject notifications. Use the RouteController.roadGraph or PassiveLocationManager.roadGraph property to get more information about the edges contained in these notifications. (#2834)
  • Note: The Mapbox Electronic Horizon feature of the Mapbox Navigation SDK is in public beta and is subject to changes, including its pricing. Use of the feature is subject to the beta product restrictions in the Mapbox Terms of Service. Mapbox reserves the right to eliminate any free tier or free evaluation offers at any time and require customers to place an order to purchase the Mapbox Electronic Horizon feature, regardless of the level of use of the feature.
  • Added the RouteController.roadObjectMatcher and PassiveLocationManager.roadObjectMatcher properties for creating user-defined road objects by matching location primitives to the road graph. (#3004)
  • Removed the Alert enumeration and the RouteAlert.alert, RouteAlert.distance, RouteAlert.length, RouteAlert.beginCoordinate, RouteAlert.endCoordinate, RouteAlert.beginSegmentIndex, and RouteAlert.endSegmentIndex properties in favor of a consolidated RouteAlerts.roadObject property. (#2991)
  • Added the RouteController.startUpdatingElectronicHorizon(with:), RouteController.stopUpdatingElectronicHorizon(), PassiveLocationManager.startUpdatingElectronicHorizon(with:) and PassiveLocationManager.stopUpdatingElectronicHorizon() methods for managing electronic horizon updates. By default electronic horizon updates are disabled. (#3475)


  • Removed the CarPlayNavigationDelegate.carPlayNavigationViewControllerDidArrive(_:) method. (#2808)
  • Renamed the CarPlayManager.mapView property to CarPlayManager.navigationMapView. (#2808)
  • Removed the CarPlayManager.overviewButton property. (#2808)
  • Removed the CarPlayNavigationViewController.drivingSide property. (#2808)
  • Added the CarPlayManagerDelegate.carPlayManager(_:shouldPresentArrivalUIFor:) and CarPlayNavigationViewController.navigationService(_:didArriveAt:) methods for determining when to present an arrival user interface. (#3016)
  • Renamed the CarPlayNavigationDelegate protocol to CarPlayNavigationViewControllerDelegate and the CarPlayNavigationViewController.carPlayNavigationDelegate property to CarPlayNavigationViewController.delegate. (#3036)
  • The CarPlayNavigationViewController.styleManager and CarPlayMapViewController.styleManager properties are now read-only. (#3137)
  • Moved the CarPlaySearchController.searchTemplate(_:updatedSearchText:completionHandler:), CarPlaySearchController.searchTemplate(_:searchTemplate:selectedResult:completionHandler:) methods to the CarPlaySearchControllerDelegate protocol. Renamed the CarPlaySearchControllerDelegate.resultsOrNoResults(_:limit:) method to CarPlaySearchControllerDelegate.searchResults(with:limit:). (#2999)
  • CarPlaySearchControllerDelegate now conforms to the CPSearchTemplateDelegate protocol. (#2999)
  • Added the NavigationGeocodedPlacemark struct, which is similar to MapboxGeocoder.swift’s GeocodedPlacemark struct but with the addition of the NavigationGeocodedPlacemark.listItem() method. Added the RecentItem struct to represent a recently selected search result. (#2999)
  • Added the CarPlayMapViewControllerDelegate protocol, which provides methods for reacting to events during the browsing and previewing activities. (#3190)
  • Added the CarPlayMapViewControllerDelegate.carPlayMapViewController(_:didAdd:pointAnnotationManager:), CarPlayNavigationViewControllerDelegate.carPlayNavigationViewController(_:didAdd:pointAnnotationManager:) and CarPlayManager.carPlayManager(_:didAdd:to:pointAnnotationManager:) delegate methods, which will be called whenever the PointAnnotation representing the final destination is added to CarPlayMapViewController, CarPlayNavigationViewController and CarPlayManager, respectively. (#3190)
  • A speed limit indicator now appears on the map during the browsing activity. (#3197)
  • A speed limit indicator now can be fully hidden by using SpeedLimitView.isAlwaysHidden property. (#3429)
  • Renamed the CarPlayManagerDelegate.carPlayManager(_:navigationServiceAlong:routeIndex:routeOptions:desiredSimulationMode:) method to CarPlayManagerDelegate.carPlayManager(_:navigationServiceFor:routeIndex:routeOptions:desiredSimulationMode:). It now returns an optional NavigationService; if it is nil, a MapboxNavigationService will be used by default. (#3208)
  • Renamed the CarPlayManagerDelegate.carplayManagerShouldDisableIdleTimer(_:) method to CarPlayManagerDelegate.carPlayManagerShouldDisableIdleTimer(_:). (#3208)
  • Added the CarPlayManagerDelegate.carPlayManager(_:templateWillAppear:animated:), CarPlayManagerDelegate.carPlayManager(_:templateDidAppear:animated:), CarPlayManagerDelegate.carPlayManager(_:templateWillDisappear:animated:), and CarPlayManagerDelegate.carPlayManager(_:templateDidDisappear:animated:) methods to pass through the corresponding methods from CPInterfaceControllerDelegate. (#3219)
  • Fixed an issue where CPMapTemplate.tripEstimateStyle uses dark appearance even if light appearance is selected. (#3397)
  • CarPlayMapViewController and CarPlayNavigationViewController are now subclassable. (#3424)
  • Added CPInterfaceController.safePopTemplate(animated:), which allows to safely pop back a CPTemplate by a single level in the template navigation hierarchy. (#3426)

User feedback

  • You can now solicit user feedback about PassiveLocationManager and NavigationMapView outside of active turn-by-turn navigation. Use PassiveLocationManager.eventsManager property of NavigationEventsManager type to create and send user feedback. You can use a FeedbackViewController to present the user with the same options as during turn-by-turn navigation. Alternatively, if you present a custom feedback UI, call the NavigationEventsManager.createFeedback() method and configure the resulting FeedbackEvent with any additional context. (#3122, #3322)
  • The ActiveNavigationEventsManagerDataSource.router, NavigationService.eventsManager, and MapboxNavigationService.eventsManager properties are no longer unsafe-unowned. (#3055)
  • Removed the EventsManager type alias. (#2993)
  • Feedback events now include a snapshot of NavigationViewController that is taken sooner, when the problem is more likely to be apparent. (#3049)
  • You can now manage the feedback event lifecycle, allowing the user to submit additional details later. Use NavigationEventsManager.createFeedback() to create a FeedbackEvent and NavigationEventsManager.sendActiveNavigationFeedback(_:type:description:) to send it to Mapbox. FeedbackEvent conforms to the Codable protocol, so your application can store incomplete feedback across sessions if necessary. (#3154, #3318)
  • To submit feedback during passive navigation, use NavigationEventsManager.createFeedback() to create a FeedbackEvent and NavigationEventsManager.sendPassiveNavigationFeedback(_:type:description:) to send it to Mapbox. This method accepts PassiveNavigationFeedbackType with feedback types specific to the passive navigation. (#3154, #3318)
  • Added an optional NavigationEventsManager.userInfo property that can be sent with all navigation events. The new property can contain application metadata, such as the application name and version, that is included in each event to help Mapbox triage and diagnose unexpected behavior. (#3007).
  • Fixed a missing feedback subtype description for LooksIncorrectSubtype.incorrectSpeedLimit and all “other” subtypes. (#3238)
  • Renamed the FeedbackViewController(eventsManager:) initializer to FeedbackViewController(eventsManager:type:). You can now customize the view controller to show only the feedback types specific to passive navigation. (#3323)
  • Renamed the FeedbackType enumeration to ActiveNavigationFeedbackType and the EventsManagerDataSource protocol to ActiveNavigationEventsManagerDataSource. (#3327)
  • Renamed the user-facing feedback categories and subcategories for active turn-by-turn navigation that are represented at runtime by the ActiveNavigationFeedbackType enumeration. (#3339
  • Added the ability to pass your own screenshot to the NavigationEventsManager.createFeedback() when a user submits a feedback. Screenshots help Mapbox to determine where issues exist for review and correction. (#3380
  • Added NavigationEventsManager.sessionId, which allows getting session identifier used in feedback and other events. (#3449)

Other changes

  • If your storyboard has a segue to NavigationViewController in Navigation.storyboard, you have to call the NavigationViewController.prepareViewLoading(routeResponse:routeIndex:routeOptions:navigationOptions:) method in your implementation of the UIViewController.prepare(for:sender:) method. (#2974, #3182)
  • Removed the NavigationViewController.origin property. (#2808)
  • Fixed a potential memory leak when using MultiplexedSpeechSynthesizer. (#3005)
  • Fixed a thread-safety issue in UnimplementedLogging protocol implementation. (#3024)
  • Fixed an issue where UIApplication.shared.isIdleTimerDisabled was not properly set in some cases. (#3245)
  • Fixed an issue where LegacyRouteController could not correctly handle arrival to the intermediate waypoint of a multi leg route. (#3483)
  • Added the Notification.Name.navigationServiceSimulationDidChange to detect when the navigation service changes the simulating status, including MapboxNavigationService.NotificationUserInfoKey.simulationStateKey and MapboxNavigationService.NotificationUserInfoKey.simulatedSpeedMultiplierKey. (#3393).

Mapbox Navigation SDK for iOS

CircleCI codecov SPM compatible CocoaPods

Mapbox Navigation SDK

Mapbox Navigation gives you all the tools you need to add turn-by-turn navigation to your iOS application.

Get up and running in a few minutes with our drop-in turn-by-turn navigation NavigationViewController, or build a completely custom turn-by-turn navigation app with our core components for routing and navigation.




The Mapbox Navigation SDK and Core Navigation are compatible with applications written in Swift 5 in Xcode 12.4 and above. The Mapbox Navigation and Mapbox Core Navigation frameworks run on iOS 11.0 and above.

The Mapbox Navigation SDK is also available for Android.


Using Swift Package Manager

To install the MapboxNavigation framework in an application using Swift Package Manager:

  1. Go to your Mapbox account dashboard and create an access token that has the DOWNLOADS:READ scope. PLEASE NOTE: This is not the same as your production Mapbox API token. Make sure to keep it private and do not insert it into any Info.plist file. Create a file named .netrc in your home directory if it doesn’t already exist, then add the following lines to the end of the file:

      login mapbox

    where PRIVATE_MAPBOX_API_TOKEN is your Mapbox API token with the DOWNLOADS:READ scope.

  2. In Xcode, go to File ‣ Swift Packages ‣ Add Package Dependency.

  3. Enter as the package repository and click Next.

  4. Set Rules to Version, Up to Next Major, and enter 2.0.0 as the minimum version requirement. Click Next.

To install the MapboxNavigation framework in another package rather than an application, run swift package init to create a Package.swift, then add the following dependency:

// Latest stable release
.package(name: "MapboxNavigation", url: "", from: "2.0.0")
// Latest prerelease
.package(name: "MapboxNavigation", url: "", .exact("2.1.0-rc.1"))

Using CocoaPods

To install the MapboxNavigation framework using CocoaPods:

  1. Go to your Mapbox account dashboard and create an access token that has the DOWNLOADS:READ scope. PLEASE NOTE: This is not the same as your production Mapbox API token. Make sure to keep it private and do not insert it into any Info.plist file. Create a file named .netrc in your home directory if it doesn’t already exist, then add the following lines to the end of the file:

      login mapbox

    where PRIVATE_MAPBOX_API_TOKEN is your Mapbox API token with the DOWNLOADS:READ scope.

  2. Create a Podfile with the following specification:

    # Latest stable release
    pod 'MapboxCoreNavigation', '~> 2.0'
    pod 'MapboxNavigation', '~> 2.0'
    # Latest prerelease
    pod 'MapboxCoreNavigation', :git => '', :tag => 'v2.1.0-rc.1'
    pod 'MapboxNavigation', :git => '', :tag => 'v2.1.0-rc.1'
  3. Run pod repo update && pod install and open the resulting Xcode workspace.

Using Carthage

To install the MapboxNavigation framework using Carthage v0.38 or above:

  1. Go to your Mapbox account dashboard and create an access token that has the DOWNLOADS:READ scope. PLEASE NOTE: This is not the same as your production Mapbox API token. Make sure to keep it private and do not insert it into any Info.plist file. Create a file named .netrc in your home directory if it doesn’t already exist, then add the following lines to the end of the file:

      login mapbox

    where PRIVATE_MAPBOX_API_TOKEN is your Mapbox API token with the DOWNLOADS:READ scope.

  2. (Optional) Clear your Carthage caches:

    rm -rf ~/Library/Caches/carthage/ ~/Library/Caches/org.carthage.CarthageKit/binaries/{MapboxCommon-ios,MapboxNavigationNative,mapbox-ios-sdk-dynamic}
  3. Create a Cartfile with the following dependency:

    # Latest stable release
    github "mapbox/mapbox-navigation-ios" ~> 2.0
    # Latest prerelease
    github "mapbox/mapbox-navigation-ios" "v2.1.0-rc.1"
  4. Run carthage bootstrap --platform iOS --use-xcframeworks --cache-builds --use-netrc.

  5. Follow the rest of Carthage’s iOS integration instructions. Your application target’s Embed Frameworks build phase should include MapboxCoreNavigation.xcframework, MapboxNavigationNative.xcframework, and MapboxCommon.xcframework.

MapboxNavigation no longer supports Carthage as of v2.0.0-alpha.1. However, if you are building a user interface from scratch, you can install just the MapboxCoreNavigation framework using Carthage.


  1. Mapbox APIs and vector tiles require a Mapbox account and API access token. In the project editor, select the application target, then go to the Info tab. Under the “Custom iOS Target Properties” section, set MBXAccessToken to your access token. You can obtain an access token from the Mapbox account page.

  2. In order for the SDK to track the user’s location as they move along the route, set NSLocationWhenInUseUsageDescription to:

    Shows your location on the map and helps improve the map.

  3. Users expect the SDK to continue to track the user’s location and deliver audible instructions even while a different application is visible or the device is locked. Go to the Signing & Capabilities tab. Under the Background Modes section, enable “Audio, AirPlay, and Picture in Picture” and “Location updates”. (Alternatively, add the audio and location values to the UIBackgroundModes array in the Info tab.)

Now import the relevant modules and present a new NavigationViewController. You can also push to a navigation view controller from within a storyboard if your application’s UI is laid out in Interface Builder.

import MapboxDirections
import MapboxCoreNavigation
import MapboxNavigation
// Define two waypoints to travel between
let origin = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.9131752, longitude: -77.0324047), name: "Mapbox")
let destination = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.8977, longitude: -77.0365), name: "White House")

// Set options
let routeOptions = NavigationRouteOptions(waypoints: [origin, destination])

// Request a route using MapboxDirections
Directions.shared.calculate(routeOptions) { [weak self] (session, result) in
    switch result {
    case .failure(let error):
    case .success(let response):
        guard let strongSelf = self else {
        // Pass the generated route response to the the NavigationViewController
        let viewController = NavigationViewController(for: response, routeIndex: 0, routeOptions: routeOptions)
        viewController.modalPresentationStyle = .fullScreen
        strongSelf.present(viewController, animated: true, completion: nil)

Consult the API reference for further details.


The API reference includes example code for accomplishing common tasks. You can run these examples as part of the navigation-ios-examples project.

This repository also contains a testbed application that exercises a variety of navigation SDK features. See the contributing guide for instructions on installing and running this application.



You can customize the appearance in order to blend in with the rest of your app. Checkout DayStyle.swift for all styleable elements.

class CustomStyle: DayStyle {
    required init() {
        mapStyleURL = URL(string: "mapbox://styles/mapbox/satellite-streets-v9")!
        styleType = .nightStyle

    override func apply() {
        BottomBannerView.appearance().backgroundColor = .orange

then initialize NavigationViewController with your style or styles:

let navigationOptions = NavigationOptions(styles: [CustomStyle()])
NavigationViewController(for: routeResponse, routeIndex: routeIndex, routeOptions: routeOptions, navigationOptions: navigationOptions)

Starting from scratch

If your application needs something totally custom, such as a voice-only experience or an unconventional user interface, consult the Core Navigation installation guide.


We welcome feedback and code contributions! Please see for details.


The Mapbox Navigation SDK for iOS is released under the Mapbox Terms of Service. See for details.


  • Swift Tools 5.3.0
View More Packages from this Author


Last updated: Thu Jan 27 2022 21:40:33 GMT-0500 (GMT-05:00)