Mapbox Navigation SDK for iOS
The Mapbox Navigation SDK gives you all the tools you need to add turn-by-turn navigation to your application. It takes just a few minutes to drop a full-fledged turn-by-turn navigation view controller into your application. Or use the Core Navigation framework directly to build something truly custom.
The Mapbox Navigation SDK and Core Navigation are compatible with applications written in Swift 5 in Xcode 10.2. The Mapbox Navigation and Mapbox Core Navigation frameworks run on iOS 10.0 and above.
Installation
Using CocoaPods
To install Mapbox Navigation using CocoaPods:
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:machine api.mapbox.com login mapbox password PRIVATE_MAPBOX_API_TOKEN
where PRIVATE_MAPBOX_API_TOKEN is your Mapbox API token with the
DOWNLOADS:READ
scope.Create a Podfile with the following specification:
pod 'MapboxNavigation', '~> 1.0'
Run
pod repo update && pod install
and open the resulting Xcode workspace.
Using Carthage
Alternatively, to install Mapbox Navigation using Carthage:
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:machine api.mapbox.com login mapbox password PRIVATE_MAPBOX_API_TOKEN
where PRIVATE_MAPBOX_API_TOKEN is your Mapbox API token with the
DOWNLOADS:READ
scope.(Optional) Clear your Carthage caches:
rm -rf ~/Library/Caches/carthage/ ~/Library/Caches/org.carthage.CarthageKit/binaries/{MapboxAccounts,MapboxCommon-ios,MapboxNavigationNative,mapbox-ios-sdk-dynamic}
Create a Cartfile with the following dependency:
github "mapbox/mapbox-navigation-ios" ~> 1.0
Configuration
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
MGLMapboxAccessToken
to your access token. You can obtain an access token from the Mapbox account page. Usage of Mapbox APIs is billed together based on monthly active users (MAU) rather than individually by HTTP request.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.
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
andlocation
values to theUIBackgroundModes
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):
print(error.localizedDescription)
case .success(let response):
guard let route = response.routes?.first, let strongSelf = self else {
return
}
// Pass the generated route to the the NavigationViewController
let viewController = NavigationViewController(for: route, routeIndex: 0, routeOptions: routeOptions)
viewController.modalPresentationStyle = .fullScreen
strongSelf.present(viewController, animated: true, completion: nil)
}
}
Starting points
This SDK is divided into two frameworks: the Mapbox Navigation framework (MapboxNavigation
) is the ready-made turn-by-turn navigation UI, while the Mapbox Core Navigation framework (MapboxCoreNavigation
) is responsible for the underlying navigation logic.
Mapbox Navigation
NavigationViewController
is the main class that encapsulates the entirety of the turn-by-turn navigation UI, orchestrating the map view, various UI elements, and the route controller. Your application would most likely present an instance of this class. The NavigationViewControllerDelegate
protocol allows your application to customize various aspects of the UI and react to location-related events as they occur.
NavigationMapView
is the map view at the center of the turn-by-turn navigation UI. You can also use this class independently of NavigationViewController
, for example to display a route preview map. The NavigationMapViewDelegate
protocol allows your application to customize various aspects of the map view’s appearance. PassiveLocationManager
is an optional alternative to CLLocationManager
for use with any standalone MGLMapView
or NavigationMapView
.
CarPlayManager
is the class that manages the CarPlay screen if your application is CarPlay-enabled. It provides a main map for browsing, a search interface powered by MapboxGeocoder.swift, and a turn-by-turn navigation UI similar to the one provided by NavigationViewController
. Your UIApplicationDelegate
subclass can conform to the CarPlayManagerDelegate
protocol to manage handoffs between NavigationViewController
and the CarPlay device, as well as to customize some aspects of the CarPlay navigation experience. To take advantage of CarPlay functionality, your application must have a CarPlay navigation application entitlement and be built in Xcode 10 or above, and the user’s iPhone or iPad must have iOS 12 or above installed.
Core Navigation
MapboxNavigationService
is responsible for receiving user location updates and determining their relation to the route line. If you build a completely custom navigation UI, this is the class your code would interact with directly. The NavigationServiceDelegate
protocol allows your application to react to location-related events as they occur. Corresponding Notification
s from the NavigationService
‘s RouteController
are also posted to the shared NotificationCenter
. These notifications indicate the current state of the application in the form of a RouteProgress
object.
For further details, consult the guides and examples included with this API reference. If you have any questions, please see our help page. We welcome your bug reports, feature requests, and contributions.
Changes in version 1.0.0
Packaging
- Carthage v0.35 or above is now required for installing this SDK if you use Carthage. (
81a36d0
) - MapboxNavigation depends on Mapbox Maps SDK for iOS v6.0.0, and MapboxCoreNavigation depends on builds of MapboxNavigationNative and MapboxCommon that require authentication. Before CocoaPods or Carthage can download Mapbox.framework, MapboxNavigationNative.framework, and MapboxCommon.framework, you need to create a special-purpose access token. See the updated installation instructions in the readme for more details. (#2437, #2477)
- If you install this SDK using Carthage, you need to also add MapboxCommon.framework to your application target’s Embed Frameworks build phase. (#2477)
- Xcode 11.4.1 or above is now required for building this SDK from source. (#2417)
- By default, usage of Mapbox APIs is now billed together based on monthly active users rather than individually by HTTP request. If you prefer to still use request-based billing, set the
MBXNavigationBillingMethod
key in Info.plist torequest
. (#2405) - Added Greek and Turkish localizations. (#2385, #2475)
- Upgraded to MapboxDirections v1.0.0, MapboxSpeech v1.0.0, and Turf v1.0.0. (#2646)
Map
- The
MGLStyle.navigationDayStyleURL
andMGLStyle.navigationNightStyleURL
properties contain URLs to the Mapbox Navigation Day and Night v5 styles, both of which show traffic congestion lines on all roads by default. The traffic congestion layer is appropriate for a preview map; to tailor the style to turn-by-turn navigation, setMGLMapView.showsTraffic
tofalse
. (#2523) - A portion of the route line now disappears behind the user puck as the user travels along the route during turn-by-turn navigation if
NavigationViewController.routeLineTracksTraversal
is set totrue
. (#2377) - Ability to hide the route line behind the user puck on CarPlay can be enabled by setting
CarPlayNavigationViewController.routeLineTracksTraversal
totrue
. (#2601) - Traffic congestion segments along the route line and the estimated arrival time periodically update to reflect current conditions when using the
DirectionsProfileIdentifier.automobileAvoidingTraffic
profile. These updates correspond to the newNotification.Name.routeControllerDidRefreshRoute
notification,NavigationServiceDelegate.navigationService(_:didRefresh:)
method, andNavigationViewControllerDelegate.navigationViewController(_:didRefresh:)
method. To disable these updates, setRouteOptions.refreshingEnabled
tofalse
. (#2366) - A building at the destination waypoint can be extruded in 3D and highlighted for emphasis and recognizability. To enable building extrusion or highlighting, set the
NavigationViewController.waypointStyle
property. For a standalone map view that is not part ofNavigationViewController
, call theNavigationMapView.highlightBuildings(at:in3D:)
method to highlight the destination building at a specific coordinate andNavigationMapView.unhighlightBuildings()
to reverse this effect. (#2535) - Replaced the
MGLStyle.navigationPreviewDayStyleURL
andMGLStyle.navigationGuidanceDayStyleURL
properties withMGLStyle.navigationDayStyleURL
, and replacedMGLStyle.navigationPreviewNightStyleURL
andMGLStyle.navigationGuidanceNightStyleURL
withMGLStyle.navigationNightStyleURL
. (#2523) - Replaced the
MGLStyle.navigationGuidanceDayStyleURL(version:)
andMGLStyle.navigationGuidanceNightStyleURL(version:)
methods withMGLStyle.navigationDayStyleURL(version:)
andMGLStyle.navigationNightStyleURL(version:)
respectively, removed theMGLStyle.navigationPreviewDayStyleURL(version:)
andMGLStyle.navigationPreviewNightStyleURL(version:)
methods. (#2567) - Removed the
NavigationViewControllerDelegate.navigationViewController(_:imageFor:)
andNavigationViewControllerDelegate.navigationViewController(_:viewFor:)
methods in favor ofMGLMapViewDelegate.mapView(_:imageFor:)
andMGLMapViewDelegate.mapView(_:viewFor:)
, respectively. (#2396) - Removed
NavigationMapViewDelegate.navigationMapView(_:routeStyleLayerWithIdentifier:source:)
,NavigationMapViewDelegate.navigationMapView(_:routeCasingStyleLayerWithIdentifier:source:)
in favor of four new delegate methods to customize the route styling (#2377):NavigationMapViewDelegate.navigationMapView(_:mainRouteStyleLayerWithIdentifier:source:)
to style the main route.NavigationMapViewDelegate.navigationMapView(_:mainRouteCasingStyleLayerWithIdentifier:source:)
to style the casing of the main route.NavigationMapViewDelegate.navigationMapView(_:alternativeRouteStyleLayerWithIdentifier:source:)
to style alternative routes.NavigationMapViewDelegate.navigationMapView(_:alternativeRouteCasingStyleLayerWithIdentifier:source:)
to style the casing of alternative routes.
- Removed the deprecated
NavigationMapView.showRoutes(_:legIndex:)
method in favor ofNavigationMapView.show(_:legIndex:)
andNavigationMapView.showWaypoints(_:legIndex:)
in favor ofNavigationMapView.showWaypoints(on:legIndex:)
. (#2539) - Fixed an issue where the casing for the main route would not overlap alternative routes. (#2377)
- Fixed memory leaks after disconnecting the application from CarPlay. (#2470)
- Fixed issue which was causing incorrect alignment of
MGLMapView.attributionButton
andMGLMapView.logoView
. (#2613)
Visual and spoken instructions
- As the user approaches certain junctions, an enlarged illustration of the junction appears below the top banner to help the user understand a complex maneuver. These junction views only appear when the relevant data is available. Contact your Mapbox sales representative or support team for access to the junction views feature. (#2408)
- Replaced
RouteVoiceController
andMapboxVoiceController
withMultiplexedSpeechSynthesizer
.MultiplexedSpeechSynthesizer
coordinates multiple cascading speech synthesizers. By default, the controller still tries to speak instructions via the Mapbox Voice API (MapboxSpeechSynthesizer
) before falling back to VoiceOver (SystemSpeechSynthesizer
), but you can also provide your own speech synthesizer that conforms to theSpeechSynthesizing
protocol. (#2348) - Added an alternative presentation for maneuver instructions that resembles swipeable user notification cards. To replace the conventional
TopBannerViewController
presentation with the cardlike presentation, create an instance ofInstructionsCardViewController
and pass it into theNavigationOptions(styles:navigationService:voiceController:topBanner:bottomBanner:)
method. (#2149, #2296, #2627)
Feedback
- The user can optionally provide more detailed feedback during turn-by-turn navigation. After tapping the feedback button and selecting a feedback type, the user is taken to a second screen for selecting from among multiple subtypes. Set the
FeedbackViewController.detailedFeedbackEnabled
property totrue
to enable two-step feedback. (#2544) - Reorganized
FeedbackType
cases (#2419):- Removed
FeedbackType.accident
,FeedbackType.hazard
,FeedbackType.reportTraffic
, andFeedbackType.mapIssue
. - Renamed
FeedbackType.roadClosed
andFeedbackType.notAllowed
toFeedbackType.roadClosure(subtype:)
andFeedbackType.illegalRoute(subtype:)
, respectively. - Renamed
FeedbackType.routingError
toFeedbackType.routeQuality(subtype:)
. - Renamed
FeedbackType.confusingInstruction
toFeedbackType.confusingAudio(subtype:)
. - Added
FeedbackType.incorrectVisual(subtype:)
,FeedbackType.routeQuality(subtype:)
, andFeedbackType.positioning(subtype:)
. FeedbackType.missingRoad
is now represented asFeedbackType.routeQuality(subtype:)
with a subtype ofRouteQualitySubtype.routeIncludedMissingRoads
.FeedbackType.missingExit
is now represented asFeedbackType.incorrectVisual(subtype:)
with a subtype ofIncorrectVisualSubtype.exitInfoIncorrect
.
- Removed
FeedbackViewController
no longer dismisses automatically after 10 seconds. (#2420)- Refreshed the feedback type icons. (#2419, #2421)
- Fixed warnings in Interface Builder that prevented styling of UI components in
EndOfRouteViewController
. (#2518)
User location
- Improved the accuracy of location tracking and off-route detection. (#2319)
- Added the
PassiveLocationManager
class for use with theMGLMapView.locationManager
property. UnlikeCLLocationManager
, this class causes the map view to display user locations snapped to the road network, just like during turn-by-turn navigation. To receive these locations without anMGLMapView
, use thePassiveLocationDataSource
class and implement thePassiveLocationDataSourceDelegate.passiveLocationDataSource(_:didUpdateLocation:rawLocation:)
method or observeNotification.Name.passiveLocationDataSourceDidUpdate
notifications. (#2410) - The
NavigationViewController.route
andNavigationService.route
properties are now read-only. To change the route that the user is traveling along, set theNavigationViewController.indexedRoute
orNavigationService.indexedRoute
property instead, pairing the route with the index of the route in the originalRouteResponse
object. (#2366) - The following methods now require a route index to be passed in as an argument (#2366):
NavigationViewController(for:routeIndex:routeOptions:navigationOptions:)
NavigationViewController(route:routeIndex:routeOptions:navigationService:)
CarPlayManagerDelegate.carPlayManager(_:navigationServiceAlong:routeIndex:routeOptions:desiredSimulationMode:)
MapboxNavigationService(route:routeIndex:routeOptions:)
MapboxNavigationService(route:routeIndex:routeOptions:directions:locationSource:eventsManagerType:simulating:routerType:)
RouteProgress(route:routeIndex:options:legIndex:spokenInstructionIndex:)
RouteProgress(route:routeIndex:options:legIndex:spokenInstructionIndex:)
Router(along:routeIndex:options:directions:dataSource:)
RouteController(along:routeIndex:options:directions:dataSource:)
- Fixed an issue where location tracking would pause at the beginning of a route after setting
RouteOptions.shapeFormat
toRouteShapeFormat.polyline
orRouteShapeFormat.geoJSON
. Note that you most likely do not need to override the default value ofRouteShapeFormat.polyline6
: this is the least bandwidth-intensive format, andRoute.shape
andRouteStep.shape
are set toLineString
s regardless. (#2319) - Fixed an issue where various delegate methods omitted
CLLocation.courseAccuracy
andCLLocation.speedAccuracy
properties from passed-inCLLocation
objects when usingRouteController
, even when these properties are provided by Core Location on iOS 13.4 and above. (#2417) - Fixed issues where the user puck would sometimes drift away from the route line even though the user was following the route. (#2412, #2417)
- Fixed an issue where
RouteController
took longer than usual to detect that the user had gone off-route. (#2412) - Fixed an issue where
RouteController
would detect that the user had gone off-route due to a single errant location update. (#2412, #2417) - Fixed an issue where the camera and user puck would cut a corner when making a turn at speed. (#2412)
- Fixed an issue where
RouteController
became too sensitive to the user going off-route near “intersections” that the Mapbox Directions API synthesizes at road classification changes, such as at either end of a tunnel. (#2412) - If the user’s raw course as reported by Core Location differs significantly from the direction of the road ahead, the camera and user puck are oriented according to the raw course. (#2417)
RouteController
now tracks the user’s location more accurately within roundabouts. (#2417)- Fixed an issue where departure instructions were briefly missing when beginning turn-by-turn navigation. (#2417)
- Removed the
RouteController.projectedLocation(for:)
method in favor ofRouteController.location
. It is no longer possible to predict the user’s location at an arbitrary time. (#2610) - Renamed the
Router.advanceLegIndex(location:)
method toRouter.advanceLegIndex()
. It is no longer possible to advance to an arbitrary leg using this method. (#2610)
Other changes
- The
RouteProgress.congestionTravelTimesSegmentsByStep
andRouteProgress.congestionTimesPerStep
properties are now read-only. (#2624) - Deprecated
NavigationDirectionsCompletionHandler
,OfflineRoutingError
,UnpackProgressHandler
,UnpackCompletionHandler
,OfflineRouteCompletionHandler
, andNavigationDirections
. UseDirections
instead ofNavigationDirections
to calculate a route. (#2509) - The
RouteLegProgress.congestionTravelTimesSegmentsByStep
andRouteLegProgress.congestionTimesPerStep
properties are now read-only. (#2615)