# mapbox-navigation-ios: turn-by-turn navigation you drop into an app

> The Mapbox Navigation SDK for iOS is a Swift package that provides both a ready-made NavigationViewController and the lower level routing and navigation components behind it, with CarPlay support and day and night map styles. It is aimed at iOS teams building delivery, transit or ride apps that need navigation rather than a mapping view.

**mapbox/mapbox-navigation-ios** — Turn-by-turn navigation logic and UI in Swift on iOS

- Repository: https://github.com/mapbox/mapbox-navigation-ios
- Website: https://docs.mapbox.com/ios/navigation/
- Stars: 919 · Forks: 328
- Language: Swift
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/mapbox-mapbox-navigation-ios

## Two entry points: the view controller or the components

Mapbox Navigation gives you all the tools you need to add turn-by-turn navigation to your iOS application, and the README offers two ways of using them. You can get up and running in a few minutes with the drop-in turn-by-turn navigation `NavigationViewController`, or build a completely custom turn-by-turn navigation app with the core components for routing and navigation.

That split is the design decision worth understanding before anything else. The drop-in controller is a full navigation UI for iPhone, iPad and CarPlay, ready to drop into your application. The core is the routing and navigation engine without that UI.

The feature list explains why a team would want one over the other. There is a full-fledged turn-by-turn navigation UI for iPhone, iPad and CarPlay, professionally designed map styles for daytime and nighttime driving, worldwide driving, cycling and walking directions powered by open data and user feedback, traffic avoidance and proactive rerouting based on current conditions in over 55 countries, natural-sounding turn instructions, and support for over two dozen languages.

CarPlay is worth calling out separately, because it is not a detail you can bolt on later. Supporting it means your navigation session has to be handed to the system through a CarPlay template, and the examples folder in this repository has a dedicated `CarPlayExample` for it.

The Android counterpart exists as a separate repository, mapbox-navigation-android, and the two are not the same codebase.

## A public access token, and no secret download token

The installation section has a detail that used to be a common source of friction: stable releases of `MapboxNavigationCore` and `MapboxNavigationUIKit` do not require a secret download token. You only need a public access token in your app's Info.plist, in the `MBXAccessToken` key.

That distinction is worth internalising. A secret download token would be a credential in your app binary, which is the kind of thing that leaks and then appears in an issue tracker. A public access token is designed to be embedded, is scoped to what you allow from the account page, and can be revoked or rotated from the Mapbox account.

The project configuration steps follow from that. Mapbox APIs and vector tiles require a Mapbox account and an API access token, so in the project editor you select the application target, go to the Info tab, and under the Custom iOS Target Properties section set `MBXAccessToken` to your token.

The rest of the configuration is the part that trips people up, because it is about iOS behaviour rather than Mapbox behaviour.

The SDK tracks the user's location along the route, which means `NSLocationWhenInUseUsageDescription` has to be set, and the README gives the exact string to use, showing your location on the map and helps improve the map. And because users expect the SDK to keep tracking location and delivering audible instructions while another application is visible or the device is locked, the Background Modes section has to enable Audio, AirPlay, and Picture in Picture and Location updates. The alternative is adding the `audio` and `location` values to the `UIBackgroundModes` array in the Info tab.

Missing the background modes is the failure that looks like a bug in the SDK: navigation appears to work, then stops the moment the screen locks.

## Installing through Swift Package Manager

The package is SPM compatible, and the README gives the two routes.

In Xcode, you go to File, Swift Packages, Add Package Dependency, enter `https://github.com/mapbox/mapbox-navigation-ios.git` as the package repository, and then set the version rule to Version, Up to Next Major, with `3.1.0` entered as the minimum version requirement.

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

```swift
// Latest stable release
.package(url: "https://github.com/mapbox/mapbox-navigation-ios.git", from: "3.1.0")
```

One thing to check here. The documented minimum version is `3.1.0`, while the recent tags in the release history are 3.32.2, 3.32.3 and 3.33.0. The instruction is a minimum, not a pin, so an Up to Next Major rule will resolve to a recent version, but the number in the documentation is stale and worth knowing before you copy it into your own manifest and assume it describes current behaviour.

The repository layout is small and idiomatic for a Swift package: `Package.swift`, `Sources/`, `Tests/`, `docs/`, an `Examples/` directory with its own `Package.swift`, a `CHANGELOG.md` and a `LICENSE.md`.

The compatibility floor is stated plainly: the SDK and Core Navigation are compatible with applications written in Swift 5.9 in Xcode 16.0 and above, and the frameworks run on iOS 14.0 and above. Swift 5.9 and Xcode 16 are the constraint that matters for a team on an older toolchain.

## The route request pipeline in Swift

The core flow is visible in the README's example, and it is worth reading closely because the shape of the API tells you how the library is organised.

You import the modules:

```swift
import MapboxDirections
import MapboxNavigationCore
import MapboxNavigationUIKit
import UIKit
import CoreLocation
```

The entry point is a provider that owns the core:

```swift
// Define the Mapbox Navigation entry point.
let mapboxNavigationProvider = MapboxNavigationProvider(coreConfig: .init())
lazy var mapboxNavigation = mapboxNavigationProvider.mapboxNavigation
```

From there you describe the journey with waypoints and options, and ask the routing provider for a route:

```swift
// 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 options = NavigationRouteOptions(waypoints: [origin, destination])

// Request a route using RoutingProvider
let request = mapboxNavigation.routingProvider().calculateRoutes(options: options)   
Task {
    switch await request.result {
    case .failure(let error):
        print(error.localizedDescription)
    case .success(let navigationRoutes):
        // Pass the generated navigation routes to the the NavigationViewController
        let navigationOptions = NavigationOptions(mapboxNavigation: mapboxNavigation,
                                                  voiceController: mapboxNavigationProvider.routeVoiceController,
                                                  eventsManager: mapboxNavigationProvider.eventsManager())
        let navigationViewController = NavigationViewController(navigationRoutes: navigationRoutes,
                                                                navigationOptions: navigationOptions)
        navigationViewController.modalPresentationStyle = .fullScreen

        present(navigationViewController, animated: true, completion: nil)
    }
}
```

Three design points are visible. The routing call returns a request object whose `result` is awaited inside a `Task`, so the API is Swift concurrency native rather than callback based. The `NavigationOptions` object is where the voice controller and the events manager are handed to the UI, which is how the UI layer is kept separate from the engine. And the route is computed before the UI is presented, so the view controller is created with routes already in hand rather than loading them itself.

That separation is the answer to the custom UI question. If you want your own screen, you use the core, take the routes and the events manager, and build the view yourself.

## Styling per trait collection, not per screen

Customisation is handled through styles, and the example shows a specific approach that is worth copying.

```swift
class CustomStandardDayStyle: StandardDayStyle {
    required init() {
        super.init()
        mapStyleURL = URL(string: "mapbox://styles/mapbox/satellite-streets-v9")!
        styleType = .night
    }

    override func apply() {
        super.apply()
        BottomBannerView.appearance(for: UITraitCollection(userInterfaceIdiom: .phone)).backgroundColor = .orange
        BottomBannerView.appearance(for: UITraitCollection(userInterfaceIdiom: .pad)).backgroundColor = .orange
    }
}
```

A style subclasses one of the built-in ones, replaces the map style URL, and then overrides `apply()` to change the appearance of SDK views. The two `BottomBannerView.appearance(for:)` calls target a phone idiom and a pad idiom separately, because iPhone and iPad layouts differ enough that a single appearance override leaves one of them looking wrong.

The styles are then passed to the navigation options:

```swift
let navigationOptions = NavigationOptions(
            mapboxNavigation: navigationProvider.mapboxNavigation,
            voiceController: navigationProvider.routeVoiceController,
            eventsManager: navigationProvider.eventsManager(),
            styles: [CustomStandardDayStyle()]
        )
NavigationViewController(navigationRoutes: navigationRoutes, navigationOptions: navigationOptions)
```

Note that this is UIKit appearance proxy work, applied to the SDK's own views. That is the practical limit of the styling story described here. You can change the map style and tint the SDK's views, but the layout of the navigation screen is the SDK's, which is the trade for the drop-in controller.

## The Examples folder shows the core and UIKit split

The repository contains a testbed application that exercises a variety of navigation SDK features, and you need to configure a public access token to run the examples. The examples are split into `AdditionalExamples`, `CarPlayExample`, `CoreSDKExample`, `UIKitExample` and an `Examples.xcodeproj`, with their own `Package.swift` and a `Scripts` directory.

That directory listing is the fastest documentation the project has. `CoreSDKExample` is the minimal dependency, the core routing and navigation components without the bundled interface, and it is the place to look if you are building a custom navigation screen. `UIKitExample` is the drop-in path with `NavigationViewController`. `CarPlayExample` covers the system integration, which as noted is its own piece of work.

`AdditionalExamples` sits alongside them for the long tail of capabilities the feature list implies but does not spell out. And because the examples live in the same repository as the SDK, they are pinned to the same version, which means the sample code you copy is the code that matches the framework you are compiling against.

The README also notes that you can push to a navigation view controller from within a storyboard if your application's UI is laid out in Interface Builder, which is the detail that decides whether this fits a UIKit codebase that has not yet moved to SwiftUI.

## Mapbox Terms of Service, and what that means for you

The licence section is one line and it is the most consequential line in the README. The Mapbox Navigation SDK for iOS is released under the Mapbox Terms of Service. The repository licence field is classified as a custom licence that GitHub cannot classify, with a pointer to the LICENSE.md file.

This is not an open source licence, and the difference is not cosmetic. There is no copyleft obligation and no requirement to publish your application, but there are also none of the permissions an OSI licence grants you. The rights you have come from a service agreement with Mapbox rather than from a copyright grant, which means the terms can change and the SDK depends on services you do not control.

That dependency is the other half of the picture. The routing, the map styles, the voice instructions and the traffic data all come from Mapbox's servers. A public access token in `MBXAccessToken` is what authenticates those calls, and Mapbox APIs and vector tiles require a Mapbox account. So the SDK is not a self contained navigation library you can run offline or vendor into a closed product without further consideration.

The maintenance picture, meanwhile, is current. The releases are 3.32.2 on 2026-10-15, 3.33.0 on 2026-10-16 and 3.32.3 on 2026-10-19, with the last push on 2026-10-19. That cadence, a patch release three days after a minor one, is what a service-backed SDK looks like when the service changes.

If your product needs navigation and the Mapbox relationship is acceptable, the SDK removes a large amount of work. If you need navigation without a service dependency or without a proprietary terms agreement, the core value here, the route computation and turn-by-turn logic, is exactly the part you would have to build yourself.

## Conclusion

Adopt mapbox-navigation-ios when your iOS app needs a full navigation session, voice instructions and rerouting, and you are prepared to depend on Mapbox's routing service and its terms rather than on an open source licence. Skip it if you only need a map with a route drawn on it, since that is a much smaller dependency, or if your product cannot live with a service-backed routing layer. Verify first that the SPM minimum version you pin matches the release you intend to use, since the README still shows 3.1.0 while the current tags are 3.32.3 and 3.33.0, and that your Info.plist sets `MBXAccessToken` and the background modes the SDK needs. The repository is released under the Mapbox Terms of Service, and the last push was on 2026-10-19.

## FAQ

### What do I need to install the Mapbox Navigation SDK for iOS?

The SDK is compatible with applications written in Swift 5.9 in Xcode 16.0 and above, and runs on iOS 14.0 and above. You add the package `https://github.com/mapbox/mapbox-navigation-ios.git` in Xcode or as a Swift Package Manager dependency, and you only need a public access token in your app's Info.plist under `MBXAccessToken`.

### Does the Mapbox Navigation SDK need a secret download token?

No. The README states that stable releases of `MapboxNavigationCore` and `MapboxNavigationUIKit` do not require a secret download token, and that you only need a public access token. You can obtain tokens from the Mapbox account page.

### What must I configure so navigation keeps running in the background?

Set `NSLocationWhenInUseUsageDescription`, and in the Signing and Capabilities tab enable the Background Modes entries Audio, AirPlay, and Picture in Picture and Location updates, or add the `audio` and `location` values to the `UIBackgroundModes` array in the Info tab.

### How do I request a route with the Mapbox Navigation SDK?

Create a `MapboxNavigationProvider`, build `NavigationRouteOptions` from waypoints, and call `mapboxNavigation.routingProvider().calculateRoutes(options: options)`. The returned request has a `result` you await inside a `Task`, and on success you build a `NavigationViewController` with the navigation routes and `NavigationOptions`.

### Can I customise the look of the Mapbox navigation UI?

Yes. The README shows subclassing a built-in style such as `StandardDayStyle`, replacing `mapStyleURL`, and overriding `apply()` to adjust the appearance of SDK views per trait collection. The style is then passed to `NavigationOptions` through its `styles` parameter.

### Under what terms is the Mapbox Navigation SDK for iOS released?

The README states that it is released under the Mapbox Terms of Service, and the repository licence field is classified as a custom licence that GitHub cannot classify, pointing to the LICENSE.md file. Recent releases are 3.32.2 on 2026-10-15, 3.33.0 on 2026-10-16 and 3.32.3 on 2026-10-19.

## Sources

- [Issues](https://github.com/mapbox/mapbox-navigation-ios/issues)
- [mapbox/mapbox-navigation-ios on GitHub](https://github.com/mapbox/mapbox-navigation-ios)
- [Project website](https://docs.mapbox.com/ios/navigation/)
- [README](https://github.com/mapbox/mapbox-navigation-ios/blob/main/README.md)
- [Releases](https://github.com/mapbox/mapbox-navigation-ios/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mapbox-mapbox-navigation-ios
