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 Swift Package Manager
To install the MapboxNavigation framework in an application using Swift Package Manager:
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.In Xcode, go to File ‣ Swift Packages ‣ Add Package Dependency.
Enter
https://github.com/mapbox/mapbox-navigation-ios.git
as the package repository and click Next.Set Rules to Version, Up to Next Major, and enter
2.9.0
as the minimum version requirement. Click Next.
To install the MapboxCoreNavigation framework in another package rather than an application, run swift package init
to create a Package.swift, then add the following dependency:
// Latest prerelease
.package(name: "MapboxNavigation", url: "https://github.com/mapbox/mapbox-navigation-ios.git", from: "2.9.0")
Using CocoaPods
To install the MapboxNavigation framework 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:
# Latest stable release pod 'MapboxNavigation', '~> 2.9' # Latest prerelease pod 'MapboxCoreNavigation', :git => 'https://github.com/mapbox/mapbox-navigation-ios.git', :tag => 'v2.9.0' pod 'MapboxNavigation', :git => 'https://github.com/mapbox/mapbox-navigation-ios.git', :tag => 'v2.9.0'
Run
pod repo update && pod install
and open the resulting Xcode workspace.
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
MBXAccessToken
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 strongSelf = self else {
return
}
// 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)
}
}
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. PassiveLocationProvider
is an optional alternative to CLLocationManager
for use with any standalone MapView
or NavigationMapView
.
PreviewViewController
is the class that along with the ability to display a route preview map, also allows to present banners with additional information. Such banners should conform to Banner
protocol. The Mapbox Navigation SDK also provides default banners that allow to present address of the final destination (DestinationPreviewViewController
) and route information like estimated time of arrival, total duration and distance (RoutePreviewViewController
). The PreviewViewControllerDelegate
protocol allows to observe Banner
presentation and dismissal events. Seamless transition between PreviewViewController
and NavigationViewController
can be reached by using UIViewControllerTransitioningDelegate
and replacing existing NavigationViewController.navigationMapView
instance with the one that is used in PreviewViewController
.
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 that can be powered by the Mapbox Search SDK for iOS or 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 2.9.0
Packaging
- This library now requires a minimum deployment target of iOS 12.0 or above. iOS 11.x is no longer supported. (#4142)
- This library now requires a minimum Xcode version of 13.1.0 or above. (#4239)
- MapboxCoreNavigation now requires MapboxDirections v2.8.0. (#4251)
- MapboxCoreNavigation now requires MapboxNavigationNative v119.x. (#4239)
- MapboxNavigation now requires MapboxSpeech v2.x. (#4142)
- MapboxNavigation now requires MapboxMaps v10.9.x. (#4239)
Map
- Traffic lights, stop signs, yield signs, and railroad crossings now appear along the route during turn-by-turn navigation. To disable these icons, set the
NavigationViewController.annotatesIntersectionsAlongRoute
andCarPlayNavigationViewController.annotatesIntersectionsAlongRoute
properties tofalse
. (#4185) NavigationMapView.removeAlternativeRoutes()
andNavigationMapView.removeContinuousAlternativeRoutesDurations()
were made public to provide a way to remove previously shown alternative routes and alternative routes duration annotations, respectively. (#4134)- Fixed an issue where tapping on a route duration annotation that overlaps a different route would cause the wrong route to be passed into
NavigationMapViewDelegate.navigationMapView(_:didSelect:)
orNavigationMapViewDelegate.navigationMapView(_:didSelect:)
. (#4133) - Fixed an issue where the shields in the instruction are using the style from last navigation session with the
NavigationMapView
injection used in the new session. (#4197) - Fixed an issue where the
NavigationMapView.localizeLabels()
method only localized map labels according to the user’s Preferred Language Order setting if the application also had a localization in the preferred language. (#4205) - Additional parameters were added to
FloatingButton.rounded(image:selectedImage:size:type:imageEdgeInsets:cornerRadius)
to be able to provide button type, button image edge insets and corner radius. (#4060, #4157) FloatingButton
no longer contains corner radius shadow, border is applied instead. (#4060)- Added the
NavigationViewControllerDelegate.navigationViewController(_:didSelect:)
andNavigationViewControllerDelegate.navigationViewController(_:didSelect:)
methods that allow selection of the waypoint and continuous alternative. (#4175) NavigationMapView.showcase(_:routesPresentationStyle:legIndex:animated:duration:completion:)
now contains alegIndex
parameter that allows highlighting one leg more prominently than other legs of the route. (#4211)- Fixed an issue where the route line with no traffic congestion data and multiple legs wasn’t shown correctly. (#4217)
- Fixed a crash when setting the
NavigationMapView.userLocationStyle
property toUserLocationStyle.puck3D
. (#4239)
Preview
- Added the
PreviewViewController
that along with the ability to display a route preview map allows to present banners with additional information. Such banners should conform toBanner
protocol. The Mapbox Navigation SDK also provides default banners that allow to present address of the final destination (DestinationPreviewViewController
) and route information like estimated time of arrival, total duration and distance (RoutePreviewViewController
). ThePreviewViewControllerDelegate
protocol allows to observeBanner
presentation and dismissal events. Seamless transition betweenPreviewViewController
andNavigationViewController
can be reached by usingUIViewControllerTransitioningDelegate
and replacing existingNavigationViewController.navigationMapView
instance with the one that is used inPreviewViewController
. (#4227, #4188)
Banners and guidance instructions
- Added replacement for
VisualInstruction.maneuverImageSet(side:)
method to generate a maneuver image on iOS 13 and above. (#4161) - Road shield images are now cached and re-used across multiple application sessions. (#3930)
- Fixed an issue where the CarPlay style change would affect the style of Mapbox designed shields on mobile. (#3930)
- Fixed an issue where the Mapbox designed shields and generic shields have different sizes in instruction banner. (#3930)
- Turn lane indications now appear even if they slightly differ from what the routing engine would have inferred from the road geometry, For example, turn lanes now appear where the user is expected to use a lane marked as as a right turn lane to make a slight right turn. (#4191)
- Route shields now respect language-specific route numbers in Japan. (#4191)
- Improved the timing of some spoken instructions. (#4191)
- Fixed an issue where the current road name label appeared even while the user is not traveling on a known road. (#4191)
- Fixed an issue where top and bottom banners were not presented when starting active navigation session. (#4222)
Location tracking
- Fixed an issue where the user’s location history was sometimes matched to unnavigable paths, leading to unreliable location snapping. (#4191)
- Fixed an issue where the
RoadObjectMatcher.matchOpenLR(location:identifier:)
method would incorrectly match some TPEG OpenLR identifiers. (#4191) - Added
HistoryReader
for parsing history files. (#4194)
Routing
IndexedRouteResponse
is now the preferred way for setting up routing information for navigation.NavigationViewController
,MapboxNavigationService
,Router
andRoutingProvider
are updated to accomodate this change. (#4127)- Added the
RouteController.prefersOnlineRoute
property, which lets you automatically switch from a route generated on the device to one generated by the Mapbox Directions API if the geometries match. UseNavigationViewControllerDelegate.navigationViewController(_:didSwitchToCoincidentOnlineRoute:)
,NavigationServiceDelegate.navigationService(_:didSwitchToCoincidentOnlineRoute:)
,RouterDelegate.router(_:didSwitchToCoincidentOnlineRoute:)
or.routeControllerDidSwitchToCoincidentOnlineRoute
notification to track such events. (#4127) - Added the
NavigationViewController(for:routeIndex:navigationOptions:)
initializer to start turn-by-turn navigation using map matching response. (#4127) - Fixed an issue where continuous alternative route lines and their corresponding callouts were misplaced on long routes. (#4176)
- Added
ReplayLocationManager(history:)
andMapboxNavigationService(history:customRoutingProvider:credentials:eventsManagerType:routerType:customActivityType:)
for replaying trips recorded by a history file. (#4194) - Fixed an issue where after route refresh, the
RouteStepProgress.userDistanceToUpcomingIntersection
,RouteStepProgress.intersectionsIncludingUpcomingManeuverIntersection
,RouteStepProgress.intersectionDistances
andRouteStepProgress.intersectionIndex
are all set to default values. (#4193) - Route refreshing now respects current user progress on a leg to reduce update size and improve updating longer routes. (#4111)
- Added
RoutingProvider.refreshRoute(indexedRouteResponse:fromLegAtIndex:routeShapeIndex:legShapeIndex:completionHandler:)
to request a refresh starting from specified shape index. UpdatedRouteLegProgress
andRouteProgress
initializers to include shape indices, and addedRouteProgress.refreshRoute(with:at:legIndex:legShapeIndex:)
to apply partial route refresh. (#4111) - Fixed an issue where some alternative routes did not begin at the user’s current location or did not end at the same location as the main route. (#4191)
- Fixed an issue where some continuous alternative routes were unavailable or not consistently available when the user is traveling at low speed. (#4191)
- Fixed an issue where the values of
RouteLeg.segmentDistances
andRouteLeg.expectedTravelTime
did not add up toRouteLeg.distance
andRouteLeg.expectedTravelTime
, respectively. Each value ofRouteLeg.expectedTravelTime
that immediately follows an intersection now includes the time required to traverse the intersection. (#4191) - Fixed an issue where some rat runs were suggested as alternative routes that matched the main route. These alternative routes are no longer suggested at all. (#4191)
- Fixed an issue where routes avoided roads with the deprecated tags
hov=lane
andhov:conditional=lane @ …
as restricted roads. (#4191) - Fixed an issue where the user’s location would get out of sync after traveling through short tunnels. (#4239)
- Fixed a crash after changing
RouteController.prefersOnlineRoute
fromfalse
totrue
. (#4239)
User feedback
- The MapboxMobileEvents dependency is no longer used. Feedback events are now handled by MapboxCommon. (#4011)
- Deprecated
NavigationEventsManager.init(activeNavigationDataSource:passiveNavigationDataSource:accessToken:mobileEventsManager:)
in favor ofNavigationEventsManager.init(activeNavigationDataSource:passiveNavigationDataSource:accessToken:)
. (#4011)
Predictive caching
- Implemented predictive cache with
TilesetDescriptor
so that volatile sources are not loaded unexpectedly. (#4213) - Deprecated
PredictiveCacheManager.init(predictiveCacheOptions:styleSourcePaths:)
andPredictiveCacheManager.init(predictiveCacheOptions:mapOptions:)
in favor ofPredictiveCacheManager.init(predictiveCacheOptions:cacheMapOptions:)
. (#4213) - Added
PredictiveCacheMapsOptions
(map specific, that also allow to specify zoom levels for which the map tiles should be cached) andPredictiveCacheNavigationOptions
(navigation specific) available through thePredictiveCacheOptions
. (#4213) - Deprecated
PredictiveCacheOptions.currentLocationRadius
,PredictiveCacheOptions.routeBufferRadius
,PredictiveCacheOptions.destinationLocationRadius
,PredictiveCacheOptions.maximumConcurrentRequests
. UsePredictiveCacheOptions.predictiveCacheNavigationOptions
andPredictiveCacheOptions.predictiveCacheMapsOptions
instead for separate predictive cache configuration for maps and navigation. (#4213) - Added
PredictiveCacheManager.updateMapControllers(cacheMapOptions:)
for cashing map styles after they are loaded. (#4213)
Other changes
- Added
NavigationViewController.usesNightStyleInDarkMode
property to control whether night style is used in dark mode. (#4143) - Fixed an issue where the rerouting audio cue stopped background audio. (#3642)
- Fixed an issue where the rerouting audio cue played even if
RouteVoiceController.playRerouteSound
was set tofalse
. (#4214) - Added
BorderCrossing.init(from:to:)
to allow creation ofBorderCrossing
publicly. (#4226)