MapboxDirections
MapboxDirections.swift 可以轻松地将您的 iOS、macOS、tvOS 或 watchOS 应用连接到 Mapbox Directions API。快速获取驾驶、骑行或步行路线,无论是一次性出行或多点停留,都可以使用类似 MapKit 的 MKDirections
API 的简单界面。Mapbox Directions API 由 OSRM 路由引擎和 OpenStreetMap 项目提供的数据驱动。
尽管其名称为 MapboxDirections.swift,但它除了 Swift 3 以外,还适用于 Objective-C 和 Cocoa-AppleScript 代码。
MapboxDirections.swift 与 MapboxGeocoder.swift、MapboxStatic.swift、iOS 的 Mapbox Navigation SDK 以及 Mapbox iOS SDK 或 macOS SDK 等产品配合使用效果良好。
开始使用
在您的Cartfile中指定以下依赖项
github "mapbox/MapboxDirections.swift" ~> 0.9
或在您的CocoaPods Podfile中
pod 'MapboxDirections.swift', '~> 0.9'
然后导入import MapboxDirections
或@import MapboxDirections;
。
v0.7.0是MapboxDirections.swift的最后一个Swift 2.3编写的版本。对应的swift2.3
分支包括这个版本以及自那时以来应用的任何关键错误修复。所有后续版本都将基于编写为Swift 3的master
分支。下面的Swift示例是使用Swift 3编写的;有关Swift 2.3示例,请参阅swift2.3
分支的readme。
此存储库包含使用Swift和Objective-C编写的示例应用程序,展示了如何使用该框架。要运行它们,您需要使用0.19或更高版本的Carthage来安装依赖项。更多示例和详细文档可在Mapbox API文档中找到。
用法
为了使用此API,您需要一个Mapbox访问令牌。如果您已经使用了Mapbox iOS SDK或macOS SDK,只要您将其放置在您的应用程序的Info.plist文件中的MGLMapboxAccessToken
键中,MapboxDirections.swift就会自动识别您的访问令牌。
以下示例分别提供Swift(用main.swift
表示),Objective-C(用main.m
表示),以及AppleScript(用AppDelegate.applescript
表示)语言版本。
基础
主要方向类是 Direction(在 Swift 中)或 MBDirection(在 Objective-C 或 AppleScript 中)。使用您的访问令牌创建一个方向对象
// 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#>"
或者,您可以将访问令牌放在您应用的 Info.plist 文件中的 MGLMapboxAccessToken
键中,然后使用共享的方向对象
// main.swift
let directions = Directions.shared
// main.m
MBDirections *directions = [MBDirections sharedDirections];
-- AppDelegate.applescript
set theDirections to sharedDirections of MBDirections of the current application
拥有方向对象后,构建一个 RouteOptions 或 MBRouteOptions 对象,并将其传递到 Directions.calculate(_:completionHandler:)
方法中。
// 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: .automobileAvoidingTraffic)
options.includesSteps = true
let task = directions.calculate(options) { (waypoints, routes, error) in
guard error == nil else {
print("Error calculating directions: \(error!)")
return
}
if let route = routes?.first, let leg = route.legs.first {
print("Route via \(leg):")
let distanceFormatter = LengthFormatter()
let formattedDistance = distanceFormatter.string(fromMeters: route.distance)
let travelTimeFormatter = DateComponentsFormatter()
travelTimeFormatter.unitsStyle = .short
let formattedTravelTime = travelTimeFormatter.string(from: route.expectedTravelTime)
print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)")
for step in leg.steps {
print("\(step.instructions)")
let formattedDistance = distanceFormatter.string(fromMeters: 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:MBDirectionsProfileIdentifierAutomobileAvoidingTraffic];
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-traffic"
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
此库默认使用 Mapbox Directions API 的第 5 版。要使用第 4 版,将 RouteOptions 替换为 RouteOptionsV4(或将 MBRouteOptions 替换为 MBRouteOptionsV4)。
使用其他Mapbox库
在地图上绘制路线
使用Mapbox iOS SDK或macOS SDK,您可以轻松地在Swift或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: .zero, 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);
}
显示逐段导航界面
请参见Mapbox Navigation SDK for iOS文档中的使用示例。
测试
要运行包含的单元测试,您需要使用 Carthage 0.19 或更高版本来安装依赖项。
carthage build --platform iOS
打开 MapboxDirections.xcodeproj
- 转到 Product -> 测试。