Open 1ec5 opened 4 years ago
As a workaround, an application using NavigationViewController can implement the prompt described above by setting Router.reroutesProactively
to false
:
let router = navigationViewController.navigationService.router
router.reroutesProactively = false
then reimplementing much of the logic in InternalRouter.checkForFasterRoute(from:routeProgress:)
. Most likely, the application’s reimplementation can be a lot simpler than what’s in MapboxCoreNavigation, especially if the application doesn’t use alternative routes or silent waypoints (that is, all the waypoints separate legs, which is the default). Here’s a broad outline:
NavigationViewControllerDelegate.navigationViewController(_:didUpdate:with:rawLocation:)
to check for a new route every RouteControllerProactiveReroutingInterval
seconds on a Timer.Directions.calculate(_:completionHandler:)
to get the new route. If the new route is at least 10% faster than the existing route (based on RouteProgress.durationRemaining
), then set NavigationService.indexedRoute
to change the route to the new route.We could implement these delegate methods as a first step before implementing any new UI.
Adding NavigationServiceDelegate.navigationService(_:shouldProactivelyRerouteFrom:to:)
and NavigationViewController.navigationViewController(_:shouldProactivelyRerouteFrom:to:)
methods would be very simple on our side. Then the workaround would become much simpler, for example:
extension MyViewController: NavigationViewControllerDelegate {
func navigationViewController(_ navigationViewController: NavigationViewController, shouldProactivelyRerouteFrom currentRoute: Route, to proposedRoute: Route) {
presentProactiveReroutingPrompt(for: proposedRoute)
return false
}
@IBAction func didAcceptProposedRoute(_ sender: Any) {
guard let promptViewController = sender as? ProactiveReroutingPromptViewController else { return }
navigationViewController.navigationService.indexedRoute = (promptViewController.proposedRoute, 0)
}
}
Fixed in #4229.
Oh, actually, #4229 adds the underlying functionality but we still need default UI for this.
As long as
Router.reroutesProactively
is set totrue
, RouteController or LegacyRouteController automatically reroutes the user when it finds a faster route (subject to some heuristics around the time remaining to the destination). However, some applications may want to give the user the opportunity to accept or reject the new route, since the existing route is still valid.NavigationViewController should optionally present a transient prompt upon receiving a faster route and reroute or stay on the current route based on the user’s choice. In CarPlay, the same UI can be implemented as a CPNavigationAlert with a duration. Both UIs would depend on new
RouterDelegate.router(_:shouldProactivelyRerouteFrom:to:)
andNavigationServiceDelegate.navigationService(_:shouldProactivelyRerouteFrom:to:)
methods, which a custom UI could use to independently implement this prompt.At the point where we set the new route, we currently only check a hard-coded heuristic, but this is a good opportunity to call
RouterDelegate.router(_:shouldProactivelyRerouteFrom:to:)
and perhaps alsoMapboxNavigationService.router(_:shouldRerouteFrom:)
:https://github.com/mapbox/mapbox-navigation-ios/blob/0f00c9d3e36791b479e0a72e7937c37c1c089d16/MapboxCoreNavigation/Router.swift#L221-L223 https://github.com/mapbox/mapbox-navigation-ios/blob/0f00c9d3e36791b479e0a72e7937c37c1c089d16/MapboxCoreNavigation/RouteController.swift#L247-L248
We could implement these delegate methods as a first step before implementing any new UI.
There isn’t a perfect analogue on Android, but apparently an Android application can implement a callback similar to
NavigationViewController.navigationService(_:didRerouteAlong:at:proactive:)
; the difference is that the Android application is responsible for setting the new route, whereas on iOS the SDK takes care of setting the new route automatically./cc @mapbox/navigation-ios