MapboxDirections.swift makes it easy to connect your iOS, macOS, tvOS, or watchOS application to the Mapbox Directions API. Quickly get driving, cycling, or walking directions, whether the trip is nonstop or it has multiple stopping points, all using a simple interface reminiscent of MapKit’s MKDirections
API. The Mapbox Directions API is powered by the OSRM routing engine and open data from the OpenStreetMap project.
Despite its name, MapboxDirections.swift works in Objective-C and Cocoa-AppleScript code in addition to Swift.
MapboxDirections.swift pairs well with MapboxGeocoder.swift, MapboxStatic.swift, and the Mapbox iOS SDK or macOS SDK.
Specify the following dependency in your CocoaPods Podfile:
pod 'MapboxDirections.swift', :git => 'https://github.com/mapbox/MapboxDirections.swift.git', :tag => 'v0.6.0'
Or in your Carthage Cartfile:
github "raphaelmor/Polyline" ~> 3.2
github "Mapbox/MapboxDirections.swift" ~> 0.6.0
Then import MapboxDirections
or @import MapboxDirections;
.
This repository includes a example application written in Swift demonstrating how to use the framework. More examples and detailed documentation are available in the Mapbox API Documentation.
You’ll need a Mapbox access token in order to use the API. If you’re already using the Mapbox iOS SDK or macOS SDK, MapboxDirections.swift automatically recognizes your access token, as long as you’ve placed it in the MGLMapboxAccessToken
key of your application’s Info.plist file.
The main directions class is Directions (in Swift) or MBDirections (in Objective-C or AppleScript). Create a directions object using your access token:
// main.swift
import MapboxDirections
let directions = Directions(accessToken: "<#your access token#>")
// main.m
@import MapboxDirections;
MBDirections *directions = [[MBDirections alloc] initWithAccessToken:@"<#your access token#>"];
-- AppDelegate.applescript
set theDirections to alloc of MBDirections of the current application
tell theDirections to initWithAccessToken:"<#your access token#>"
Alternatively, you can place your access token in the MGLMapboxAccessToken
key of your application’s Info.plist file, then use the shared directions object:
// main.swift
let directions = Directions.sharedDirections
// main.m
MBDirections *directions = [MBDirections sharedDirections];
-- AppDelegate.applescript
set theDirections to sharedDirections of MBDirections of the current application
With the directions object in hand, construct a RouteOptions or MBRouteOptions object and pass it into the Directions.calculateDirections(options:completionHandler:)
method.
// main.swift
let waypoints = [
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.9131752, longitude: -77.0324047), name: "Mapbox"),
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.8977, longitude: -77.0365), name: "White House"),
]
let options = RouteOptions(waypoints: waypoints, profileIdentifier: MBDirectionsProfileIdentifierAutomobile)
options.includesSteps = true
let task = directions.calculateDirections(options: options) { (waypoints, routes, error) in
guard error == nil else {
print("Error calculating directions: \(error!)")
return
}
if let route = routes?.first, leg = route.legs.first {
print("Route via \(leg):")
let distanceFormatter = NSLengthFormatter()
let formattedDistance = distanceFormatter.stringFromMeters(route.distance)
let travelTimeFormatter = NSDateComponentsFormatter()
travelTimeFormatter.unitsStyle = .Short
let formattedTravelTime = travelTimeFormatter.stringFromTimeInterval(route.expectedTravelTime)
print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)")
for step in leg.steps {
print("\(step.instructions)")
let formattedDistance = distanceFormatter.stringFromMeters(step.distance)
print("— \(formattedDistance) —")
}
}
}
// main.m
NSArray<MBWaypoint *> *waypoints = @[
[[MBWaypoint alloc] initWithCoordinate:CLLocationCoordinate2DMake(38.9131752, -77.0324047) coordinateAccuracy:-1 name:@"Mapbox"],
[[MBWaypoint alloc] initWithCoordinate:CLLocationCoordinate2DMake(38.8977, -77.0365) coordinateAccuracy:-1 name:@"White House"],
];
MBRouteOptions *options = [[MBRouteOptions alloc] initWithWaypoints:waypoints
profileIdentifier:MBDirectionsProfileIdentifierAutomobile];
options.includesSteps = YES;
NSURLSessionDataTask *task = [directions calculateDirectionsWithOptions:options
completionHandler:^(NSArray<MBWaypoint *> * _Nullable waypoints,
NSArray<MBRoute *> * _Nullable routes,
NSError * _Nullable error) {
if (error) {
NSLog(@"Error calculating directions: %@", error);
return;
}
MBRoute *route = routes.firstObject;
MBRouteLeg *leg = route.legs.firstObject;
if (leg) {
NSLog(@"Route via %@:", leg);
NSLengthFormatter *distanceFormatter = [[NSLengthFormatter alloc] init];
NSString *formattedDistance = [distanceFormatter stringFromMeters:leg.distance];
NSDateComponentsFormatter *travelTimeFormatter = [[NSDateComponentsFormatter alloc] init];
travelTimeFormatter.unitsStyle = NSDateComponentsFormatterUnitsStyleShort;
NSString *formattedTravelTime = [travelTimeFormatter stringFromTimeInterval:route.expectedTravelTime];
NSLog(@"Distance: %@; ETA: %@", formattedDistance, formattedTravelTime);
for (MBRouteStep *step in leg.steps) {
NSLog(@"%@", step.instructions);
NSString *formattedDistance = [distanceFormatter stringFromMeters:step.distance];
NSLog(@"— %@ —", formattedDistance);
}
}
}];
-- AppDelegate.applescript
set mapbox to alloc of MBWaypoint of the current application
tell mapbox to initWithCoordinate:{38.9131752, -77.0324047} coordinateAccuracy:-1 |name|:"Mapbox"
set theWhiteHouse to alloc of MBWaypoint of the current application
tell theWhiteHouse to initWithCoordinate:{38.8977, -77.0365} coordinateAccuracy:-1 |name|:"White House"
set theWaypoints to {mapbox, theWhiteHouse}
set theOptions to alloc of MBRouteOptions of the current application
tell theOptions to initWithWaypoints:theWaypoints profileIdentifier:"mapbox/driving"
set theOptions's includesSteps to true
set theURL to theDirections's URLForCalculatingDirectionsWithOptions:theOptions
set theData to the current application's NSData's dataWithContentsOfURL:theURL
set theJSON to the current application's NSJSONSerialization's JSONObjectWithData:theData options:0 |error|:(missing value)
set theRoute to alloc of MBRoute of the current application
tell theRoute to initWithJson:(the first item of theJSON's routes) waypoints:theWaypoints profileIdentifier:"mapbox/driving"
set theLeg to the first item of theRoute's legs
log "Route via " & theLeg's |name| & ":"
set theDistanceFormatter to alloc of NSLengthFormatter of the current application
tell theDistanceFormatter to init()
set theDistance to theDistanceFormatter's stringFromMeters:(theLeg's distance)
log "Distance: " & theDistance
repeat with theStep in theLeg's steps
log theStep's instructions
set theDistance to theDistanceFormatter's stringFromMeters:(theStep's distance)
log "— " & theDistance & " —"
end repeat
This library uses version 5 of the Mapbox Directions API by default. To use version 4 instead, replace RouteOptions with RouteOptionsV4 (or MBRouteOptions with MBRouteOptionsV4).
With the Mapbox iOS SDK or macOS SDK, you can easily draw the route on a map in Swift or Objective-C:
// main.swift
if route.coordinateCount > 0 {
// Convert the route’s coordinates into a polyline.
var routeCoordinates = route.coordinates!
let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: route.coordinateCount)
// Add the polyline to the map and fit the viewport to the polyline.
mapView.addAnnotation(routeLine)
mapView.setVisibleCoordinates(&routeCoordinates, count: route.coordinateCount, edgePadding: UIEdgeInsetsZero, animated: true)
}
// main.m
if (route.coordinateCount) {
// Convert the route’s coordinates into a polyline.
CLLocationCoordinate2D *routeCoordinates = malloc(route.coordinateCount * sizeof(CLLocationCoordinate2D));
[route getCoordinates:routeCoordinates];
MGLPolyline *routeLine = [MGLPolyline polylineWithCoordinates:routeCoordinates count:route.coordinateCount];
// Add the polyline to the map and fit the viewport to the polyline.
[mapView addAnnotation:routeLine];
[mapView setVisibleCoordinates:routeCoordinates count:route.coordinateCount edgePadding:UIEdgeInsetsZero animated:YES];
// Make sure to free this array to avoid leaking memory.
free(routeCoordinates);
}
To run the included unit tests, you need to use CocoaPods to install the dependencies.
pod install
open MapboxDirections.xcworkspace
- Switch to the MapboxDirections scheme and go to Product ‣ Test.
The workspace requires CocoaPods 1.1.0.beta.1 or greater if opening inside Xcode 8.