Skip to content

Commit

Permalink
Merge pull request #2350 from mapbox/jerrad/new-direction
Browse files Browse the repository at this point in the history
Directions Interface Compatibility Update
  • Loading branch information
Udumft committed Apr 17, 2020
2 parents d55481f + 4c57516 commit a5937c7
Show file tree
Hide file tree
Showing 43 changed files with 523 additions and 358 deletions.
2 changes: 1 addition & 1 deletion Cartfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
binary "https://www.mapbox.com/ios-sdk/Mapbox-iOS-SDK.json" ~> 5.6
binary "https://www.mapbox.com/ios-sdk/MapboxNavigationNative.json" ~> 6.2.1
github "mapbox/mapbox-directions-swift" == 1.0.0-alpha.1
github "mapbox/mapbox-directions-swift" "c91d3ba051fa67759b905299dad85a163697efcf"
github "mapbox/turf-swift" ~> 0.3
github "mapbox/mapbox-events-ios" ~> 0.10
github "ceeK/Solar" ~> 2.1.0
Expand Down
6 changes: 3 additions & 3 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
binary "https://www.mapbox.com/ios-sdk/Mapbox-iOS-SDK.json" "5.7.0"
binary "https://www.mapbox.com/ios-sdk/Mapbox-iOS-SDK.json" "5.8.0"
binary "https://www.mapbox.com/ios-sdk/MapboxNavigationNative.json" "6.2.1"
github "AndriiDoroshko/SnappyShrimp" "1.6.4"
github "CedarBDD/Cedar" "v1.0"
github "Quick/Nimble" "v8.0.5"
github "Quick/Nimble" "v8.0.7"
github "Quick/Quick" "v2.2.0"
github "ceeK/Solar" "2.1.0"
github "mapbox/MapboxGeocoder.swift" "v0.10.2"
github "mapbox/mapbox-directions-swift" "v1.0.0-alpha.1"
github "mapbox/mapbox-directions-swift" "c91d3ba051fa67759b905299dad85a163697efcf"
github "mapbox/mapbox-events-ios" "v0.10.2"
github "mapbox/mapbox-speech-swift" "v0.3.0"
github "mapbox/turf-swift" "v0.3.0"
Expand Down
5 changes: 3 additions & 2 deletions Example/AppDelegate+CarPlay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ extension AppDelegate: CPApplicationDelegate {

@available(iOS 12.0, *)
extension AppDelegate: CarPlayManagerDelegate {
func carPlayManager(_ carPlayManager: CarPlayManager, navigationServiceAlong route: Route, desiredSimulationMode: SimulationMode) -> NavigationService {
func carPlayManager(_ carPlayManager: CarPlayManager, navigationServiceAlong route: Route, routeOptions: RouteOptions, desiredSimulationMode: SimulationMode) -> NavigationService {

if let nvc = self.window?.rootViewController?.presentedViewController as? NavigationViewController, let service = nvc.navigationService {
//Do not set simulation mode if we already have an active navigation session.
return service
}
return MapboxNavigationService(route: route, simulating: desiredSimulationMode)
return MapboxNavigationService(route: route, routeOptions: routeOptions, simulating: desiredSimulationMode)
}

// MARK: CarPlayManagerDelegate
Expand Down
4 changes: 3 additions & 1 deletion Example/CustomViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class CustomViewController: UIViewController, MGLMapViewDelegate {
var simulateLocation = false

var userRoute: Route?

var userRouteOptions: RouteOptions?

// Start voice instructions
var voiceController: MapboxVoiceController!
Expand All @@ -38,7 +40,7 @@ class CustomViewController: UIViewController, MGLMapViewDelegate {
super.viewDidLoad()

let locationManager = simulateLocation ? SimulatedLocationManager(route: userRoute!) : NavigationLocationManager()
navigationService = MapboxNavigationService(route: userRoute!, locationSource: locationManager, simulating: simulateLocation ? .always : .onPoorGPS)
navigationService = MapboxNavigationService(route: userRoute!, routeOptions: userRouteOptions!, locationSource: locationManager, simulating: simulateLocation ? .always : .onPoorGPS)
voiceController = MapboxVoiceController(navigationService: navigationService)

mapView.delegate = self
Expand Down
2 changes: 1 addition & 1 deletion Example/ViewController+GuidanceCards.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import MapboxDirections
/// :nodoc:
extension ViewController: InstructionsCardCollectionDelegate {
public func instructionsCardCollection(_ instructionsCardCollection: InstructionsCardViewController, didPreview step: RouteStep) {
guard let route = routes?.first else { return }
guard let route = response?.routes?.first else { return }

// find the leg that contains the step, legIndex, and stepIndex
guard let leg = route.legs.first(where: { $0.steps.contains(step) }),
Expand Down
94 changes: 48 additions & 46 deletions Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import MapboxDirections
import UserNotifications
import AVKit

private typealias RouteRequestSuccess = (([Route]) -> Void)
private typealias RouteRequestSuccess = ((RouteResponse) -> Void)
private typealias RouteRequestFailure = ((Error) -> Void)

class ViewController: UIViewController {
Expand Down Expand Up @@ -35,14 +35,15 @@ class ViewController: UIViewController {
}
}

var routes: [Route]? {
var response: RouteResponse? {
didSet {
startButton.isEnabled = (routes?.count ?? 0 > 0)
guard let routes = routes, let current = routes.first else {
guard let routes = response?.routes, let current = routes.first else {
startButton.isEnabled = false
mapView?.removeRoutes()
return

}

startButton.isEnabled = true
mapView?.show(routes)
mapView?.showWaypoints(on: current)
}
Expand All @@ -52,17 +53,17 @@ class ViewController: UIViewController {

// MARK: Directions Request Handlers

fileprivate lazy var defaultSuccess: RouteRequestSuccess = { [weak self] (routes) in
guard let current = routes.first else { return }
fileprivate lazy var defaultSuccess: RouteRequestSuccess = { [weak self] (response) in
guard let routes = response.routes, !routes.isEmpty, case let .route(options) = response.options else { return }
self?.mapView?.removeWaypoints()
self?.routes = routes
self?.waypoints = current.routeOptions.waypoints
self?.response = response
self?.waypoints = options.waypoints
self?.clearMap.isHidden = false
self?.longPressHintView.isHidden = true
}

fileprivate lazy var defaultFailure: RouteRequestFailure = { [weak self] (error) in
self?.routes = nil //clear routes from the map
self?.response = nil //clear routes from the map
print(error.localizedDescription)
self?.presentAlert(message: error.localizedDescription)
}
Expand Down Expand Up @@ -207,62 +208,63 @@ class ViewController: UIViewController {
fileprivate func requestRoute(with options: RouteOptions, success: @escaping RouteRequestSuccess, failure: RouteRequestFailure?) {
// Calculate route offline if an offline version is selected
let shouldUseOfflineRouting = Settings.selectedOfflineVersion != nil
Settings.directions.calculate(options, offline: shouldUseOfflineRouting) { (waypoints, routes, error) in
if let error = error { failure?(error) }
guard let routes = routes else { return }
return success(routes)
Settings.directions.calculate(options, offline: shouldUseOfflineRouting) { (session, result) in
switch result {
case let .success(response):
success(response)
case let .failure(error):
failure?(error)
}
}
}

// MARK: Basic Navigation

func startBasicNavigation() {
guard let route = routes?.first else { return }
guard let response = response, let route = response.routes?.first, case let .route(routeOptions) = response.options else { return }

let service = navigationService(route: route)
let service = navigationService(route: route, options: routeOptions)
let navigationViewController = self.navigationViewController(navigationService: service)

presentAndRemoveMapview(navigationViewController, completion: beginCarPlayNavigation)
}

func startNavigation(styles: [Style]) {
guard let route = routes?.first else { return }
guard let response = response, let route = response.routes?.first, case let .route(routeOptions) = response.options else { return }

let options = NavigationOptions(styles: styles, navigationService: navigationService(route: route))
let navigationViewController = NavigationViewController(for: route, options: options)
let options = NavigationOptions(styles: styles, navigationService: navigationService(route: route, options: routeOptions))
let navigationViewController = NavigationViewController(for: route, routeOptions: routeOptions, navigationOptions: options)
navigationViewController.delegate = self

presentAndRemoveMapview(navigationViewController, completion: beginCarPlayNavigation)
}

func navigationViewController(navigationService: NavigationService) -> NavigationViewController {
let route = navigationService.route
let options = NavigationOptions( navigationService: navigationService)
let options = NavigationOptions(navigationService: navigationService)

let navigationViewController = NavigationViewController(for: route, options: options)
let navigationViewController = NavigationViewController(for: navigationService.route, routeOptions: navigationService.routeProgress.routeOptions, navigationOptions: options)
navigationViewController.delegate = self
navigationViewController.mapView?.delegate = self
return navigationViewController
}

public func beginNavigationWithCarplay(navigationService: NavigationService) {
self.routes = [navigationService.route]

let navigationViewController = activeNavigationViewController ?? self.navigationViewController(navigationService: navigationService)
navigationViewController.didConnectToCarPlay()

guard activeNavigationViewController == nil else { return }

presentAndRemoveMapview(navigationViewController, completion: nil)
}

// MARK: Custom Navigation UI
func startCustomNavigation() {
guard let route = routes?.first else { return }
guard let route = response?.routes?.first, let responseOptions = response?.options, case let .route(routeOptions) = responseOptions else { return }

guard let customViewController = storyboard?.instantiateViewController(withIdentifier: "custom") as? CustomViewController else { return }

customViewController.userRoute = route
customViewController.userRouteOptions = routeOptions

let destination = MGLPointAnnotation()
destination.coordinate = route.shape!.coordinates.last!
Expand All @@ -275,34 +277,34 @@ class ViewController: UIViewController {
// MARK: Styling the default UI

func startStyledNavigation() {
guard let route = routes?.first else { return }
guard let response = response, let route = response.routes?.first, case let .route(routeOptions) = response.options else { return }

let styles = [CustomDayStyle(), CustomNightStyle()]
let options = NavigationOptions(styles:styles, navigationService: navigationService(route: route))
let navigationViewController = NavigationViewController(for: route, options: options)
let options = NavigationOptions(styles:styles, navigationService: navigationService(route: route, options: routeOptions))
let navigationViewController = NavigationViewController(for: route, routeOptions: routeOptions, navigationOptions: options)
navigationViewController.delegate = self

presentAndRemoveMapview(navigationViewController, completion: beginCarPlayNavigation)
}

// MARK: Guidance Cards
func startGuidanceCardsNavigation() {
guard let route = routes?.first else { return }
guard let response = response, let route = response.routes?.first, case let .route(routeOptions) = response.options else { return }

let instructionsCardCollection = InstructionsCardViewController()
instructionsCardCollection.cardCollectionDelegate = self

let options = NavigationOptions(navigationService: navigationService(route: route), topBanner: instructionsCardCollection)
let navigationViewController = NavigationViewController(for: route, options: options)
let options = NavigationOptions(navigationService: navigationService(route: route, options: routeOptions), topBanner: instructionsCardCollection)
let navigationViewController = NavigationViewController(for: route, routeOptions: routeOptions, navigationOptions: options)
navigationViewController.delegate = self

presentAndRemoveMapview(navigationViewController, completion: beginCarPlayNavigation)
}

func navigationService(route: Route) -> NavigationService {
func navigationService(route: Route, options: RouteOptions) -> NavigationService {
let simulate = simulationButton.isSelected
let mode: SimulationMode = simulate ? .always : .onPoorGPS
return MapboxNavigationService(route: route, directions: Settings.directions, simulating: mode)
return MapboxNavigationService(route: route, routeOptions: options, directions: Settings.directions, simulating: mode)
}

func presentAndRemoveMapview(_ navigationViewController: NavigationViewController, completion: CompletionHandler?) {
Expand Down Expand Up @@ -361,7 +363,7 @@ extension ViewController: MGLMapViewDelegate {

self.mapView?.localizeLabels()

if let routes = routes, let currentRoute = routes.first, let coords = currentRoute.shape?.coordinates {
if let routes = response?.routes, let currentRoute = routes.first, let coords = currentRoute.shape?.coordinates {
mapView.setVisibleCoordinateBounds(MGLPolygon(coordinates: coords, count: UInt(coords.count)).overlayBounds, animated: false)
self.mapView?.show(routes)
self.mapView?.showWaypoints(on: currentRoute)
Expand All @@ -372,7 +374,7 @@ extension ViewController: MGLMapViewDelegate {
// MARK: - NavigationMapViewDelegate
extension ViewController: NavigationMapViewDelegate {
func navigationMapView(_ mapView: NavigationMapView, didSelect waypoint: Waypoint) {
guard let routeOptions = routes?.first?.routeOptions else { return }
guard let responseOptions = response?.options, case let .route(routeOptions) = responseOptions else { return }
let modifiedOptions = routeOptions.without(waypoint: waypoint)

presentWaypointRemovalActionSheet { _ in
Expand All @@ -381,10 +383,10 @@ extension ViewController: NavigationMapViewDelegate {
}

func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) {
guard let routes = routes else { return }
guard let routes = response?.routes else { return }
guard let index = routes.firstIndex(where: { $0 === route }) else { return }
self.routes!.remove(at: index)
self.routes!.insert(route, at: 0)
self.response!.routes!.remove(at: index)
self.response!.routes!.insert(route, at: 0)
}

private func presentWaypointRemovalActionSheet(completionHandler approve: @escaping ((UIAlertAction) -> Void)) {
Expand Down Expand Up @@ -435,22 +437,22 @@ extension ViewController: VoiceControllerDelegate {
func navigationViewController(_ navigationViewController: NavigationViewController, shouldRerouteFrom location: CLLocation) -> Bool {
let shouldUseOfflineRouting = Settings.selectedOfflineVersion != nil

guard shouldUseOfflineRouting == true else {
guard shouldUseOfflineRouting == true, let responseOptions = response?.options, case let .route(routeOptions) = responseOptions else {
return true
}

let currentRoute = navigationViewController.route
let profileIdentifier = currentRoute.routeOptions.profileIdentifier
let profileIdentifier = routeOptions.profileIdentifier

var waypoints: [Waypoint] = [Waypoint(location: location)]
var remainingWaypoints = currentRoute.routeOptions.waypoints
var remainingWaypoints = navigationViewController.navigationService.routeProgress.remainingWaypoints
remainingWaypoints.removeFirst()
waypoints.append(contentsOf: remainingWaypoints)

let options = NavigationRouteOptions(waypoints: waypoints, profileIdentifier: profileIdentifier)

Settings.directions.calculate(options, offline: true) { (waypoints, routes, error) in
guard let route = routes?.first else { return }
Settings.directions.calculate(options, offline: true) { (session, result) in
guard case let .success(response) = result, let routes = response.routes, let route = routes.first else { return }

navigationViewController.navigationService.route = route
}

Expand Down
2 changes: 1 addition & 1 deletion MapboxCoreNavigation/EventDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct NavigationEventDetails: EventDetails {
coordinate = dataSource.router.rawLocation?.coordinate
startTimestamp = session.departureTimestamp ?? nil
sdkIdentifier = defaultInterface ? "mapbox-navigation-ui-ios" : "mapbox-navigation-ios"
profile = dataSource.routeProgress.route.routeOptions.profileIdentifier.rawValue
profile = dataSource.routeProgress.routeOptions.profileIdentifier.rawValue
simulation = dataSource.locationProvider is SimulatedLocationManager.Type

sessionIdentifier = session.identifier.uuidString
Expand Down

0 comments on commit a5937c7

Please sign in to comment.