Skip to content

Commit 2a9dede

Browse files
committed
Use the provided custom route options type on reroute (#4789)
1 parent f05868d commit 2a9dede

File tree

12 files changed

+264
-33
lines changed

12 files changed

+264
-33
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changes to the Mapbox Navigation SDK for iOS
22

3+
## v2.20.2
4+
5+
### Routing
6+
7+
* Fixed the usage of the `RouteOptions` type from the initial route request instead of a hardcoded type, ensuring additional parameters are preserved on reroutes. ([#4789](https://github.com/mapbox/mapbox-navigation-ios/pull/4789))
8+
39
## v2.20.1
410

511
### Packaging

Cartfile.resolved

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
binary "https://api.mapbox.com/downloads/v2/carthage/mapbox-common/MapboxCommon.json" "23.11.4"
22
binary "https://api.mapbox.com/downloads/v2/carthage/mobile-navigation-native/MapboxNavigationNative.xcframework.json" "206.1.0"
3-
github "mapbox/mapbox-directions-swift" "v2.14.1"
3+
github "mapbox/mapbox-directions-swift" "v2.14.2"
44
github "mapbox/turf-swift" "v2.8.0"
55
github "mattgallagher/CwlPreconditionTesting" "2.2.2"
66
github "pointfreeco/swift-snapshot-testing" "1.9.0"

MapboxNavigation-SPM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MapboxNavigation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
2C856451297AE0A6006EFCBB /* NavigationEventsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C856450297AE0A6006EFCBB /* NavigationEventsManager.swift */; };
128128
2C856454297B1884006EFCBB /* NavigationCommonEventsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C856453297B1884006EFCBB /* NavigationCommonEventsManagerTests.swift */; };
129129
2C856456297B3862006EFCBB /* EventsDatasourceSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C856455297B3862006EFCBB /* EventsDatasourceSpy.swift */; };
130+
2C88591D2E5611C8009A72E5 /* CustomRouteOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C88591C2E5611C8009A72E5 /* CustomRouteOptions.swift */; };
130131
2C8BF7AE2D6C99FC00C60BD4 /* NavigationMovementMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8BF7AD2D6C99FC00C60BD4 /* NavigationMovementMonitor.swift */; };
131132
2C8BF7B02D6C9A0900C60BD4 /* NavigationMovementMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8BF7AF2D6C9A0900C60BD4 /* NavigationMovementMonitorTests.swift */; };
132133
2C9006CA291927850012CCEA /* RoutingProviderSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9006C7291927850012CCEA /* RoutingProviderSpy.swift */; };
@@ -822,6 +823,7 @@
822823
2C856450297AE0A6006EFCBB /* NavigationEventsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationEventsManager.swift; sourceTree = "<group>"; };
823824
2C856453297B1884006EFCBB /* NavigationCommonEventsManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationCommonEventsManagerTests.swift; sourceTree = "<group>"; };
824825
2C856455297B3862006EFCBB /* EventsDatasourceSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsDatasourceSpy.swift; sourceTree = "<group>"; };
826+
2C88591C2E5611C8009A72E5 /* CustomRouteOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRouteOptions.swift; sourceTree = "<group>"; };
825827
2C8BF7AD2D6C99FC00C60BD4 /* NavigationMovementMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMovementMonitor.swift; sourceTree = "<group>"; };
826828
2C8BF7AF2D6C9A0900C60BD4 /* NavigationMovementMonitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMovementMonitorTests.swift; sourceTree = "<group>"; };
827829
2C9006C7291927850012CCEA /* RoutingProviderSpy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoutingProviderSpy.swift; sourceTree = "<group>"; };
@@ -2208,6 +2210,7 @@
22082210
B47C1ACE261FD0A30078546C /* TestHelper */ = {
22092211
isa = PBXGroup;
22102212
children = (
2213+
2C88591C2E5611C8009A72E5 /* CustomRouteOptions.swift */,
22112214
2CEC5C5529F71714001B5EC2 /* NavigationSessionManagerSpy.swift */,
22122215
2CA61049297EF6D9003E49A7 /* System */,
22132216
2C2880A2291AB7240063E5B7 /* NavNative */,
@@ -3447,6 +3450,7 @@
34473450
2CA61044297E9E60003E49A7 /* TelemetrySpy.swift in Sources */,
34483451
B47C1B62261FD3BD0078546C /* DummyURLSessionDataTask.swift in Sources */,
34493452
E20E3AC526C50AC6002E13EE /* BillingServiceMock.swift in Sources */,
3453+
2C88591D2E5611C8009A72E5 /* CustomRouteOptions.swift in Sources */,
34503454
2C7FAF96291ABE62000217A7 /* TestRouteProvider.swift in Sources */,
34513455
2CAEABD32930D87B00DE851A /* RouterSpy.swift in Sources */,
34523456
E2C9D8A7268DCB7B005D8955 /* XCTestCase++.swift in Sources */,

Sources/MapboxCoreNavigation/AlternativeRoute.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@ public struct AlternativeRoute: Identifiable {
4343
/// The difference of expected travel time between alternative and the main routes
4444
public let expectedTravelTimeDelta: TimeInterval
4545

46-
init?(mainRoute: Route, alternativeRoute nativeRouteAlternative: RouteAlternative) {
46+
init?(
47+
mainRoute: Route,
48+
alternativeRoute nativeRouteAlternative: RouteAlternative,
49+
routeOptionsType: RouteOptions.Type
50+
) {
4751
self.id = nativeRouteAlternative.id
48-
guard let decoded = RerouteController.decode(routeRequest: nativeRouteAlternative.route.getRequestUri(),
49-
routeResponse: nativeRouteAlternative.route.getResponseJsonRef()) else {
52+
guard let decoded = RerouteController.decode(
53+
routeRequest: nativeRouteAlternative.route.getRequestUri(),
54+
routeResponse: nativeRouteAlternative.route.getResponseJsonRef(),
55+
type: routeOptionsType
56+
) else {
5057
return nil
5158
}
5259

Sources/MapboxCoreNavigation/HistoryReader.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Foundation
2+
import MapboxDirections
23
import MapboxNavigationNative
34

45
/// Digest of history file contents produced by `HistoryReader`.
@@ -106,7 +107,11 @@ public struct HistoryReader: Sequence {
106107
return nil
107108
}
108109
guard let responseData = routeResponse.data(using: .utf8),
109-
let decodedInfo = RerouteController.decode(routeRequest: routeRequest, routeResponse: responseData),
110+
let decodedInfo = RerouteController.decode(
111+
routeRequest: routeRequest,
112+
routeResponse: responseData,
113+
type: RouteOptions.self
114+
),
110115
let routes = decodedInfo.routeResponse.routes,
111116
routes.indices.contains(Int(setRoute.routeIndex))
112117
else {

Sources/MapboxCoreNavigation/RerouteController.swift

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import CoreLocation
12
import Foundation
23
import MapboxDirections
34
import MapboxCommon
@@ -50,13 +51,13 @@ class RerouteController {
5051
return
5152
}
5253

53-
defaultRerouteController.requestConfig = { [weak delegate] in
54-
guard let delegate = delegate,
55-
let url = URL(string: $0),
56-
let options = RouteOptions(url: url) else {
54+
defaultRerouteController.requestConfig = { [weak self] in
55+
guard let self,
56+
let delegate = self.delegate,
57+
let routeOptions = self.options(with: $0) else {
5758
return $0
5859
}
59-
return NavigationSettings.shared.directions.url(forCalculating: delegate.rerouteControllerWillModify(options: options)).absoluteString
60+
return NavigationSettings.shared.directions.url(forCalculating: delegate.rerouteControllerWillModify(options: routeOptions)).absoluteString
6061
}
6162
}
6263
}
@@ -75,6 +76,7 @@ class RerouteController {
7576
private let rerouteDetector: RerouteDetectorInterface
7677

7778
private var reroutingRequest: NavigationProviderRequest?
79+
private var initialOptions: RouteOptions?
7880
private var latestRouteResponse: (response: RouteResponse, options: RouteOptions)?
7981
private var isCancelled = false
8082

@@ -83,7 +85,12 @@ class RerouteController {
8385

8486
private weak var navigator: MapboxNavigationNative.Navigator?
8587

88+
func set(initialOptions: RouteOptions?) {
89+
self.initialOptions = initialOptions
90+
}
91+
8692
func resetToDefaultSettings() {
93+
initialOptions = nil
8794
reroutesProactively = true
8895
isCancelled = false
8996
config.setAvoidManeuverSecondsForSeconds(NSNumber(value: Self.DefaultManeuverAvoidanceRadius))
@@ -117,12 +124,21 @@ class RerouteController {
117124
deinit {
118125
invalidate()
119126
}
127+
128+
fileprivate var optionsType: RouteOptions.Type {
129+
initialOptions.map { Swift.type(of: $0) } ?? RouteOptions.self
130+
}
131+
132+
fileprivate func options(with url: String) -> RouteOptions? {
133+
Self.decodeRouteOptions(with: url, type: optionsType)
134+
}
120135
}
121136

122137
extension RerouteController: RerouteObserver {
123138
func onSwitchToAlternative(forRoute route: RouteInterface) {
124139
guard let decoded = Self.decode(routeRequest: route.getRequestUri(),
125-
routeResponse: route.getResponseJsonRef()) else {
140+
routeResponse: route.getResponseJsonRef(),
141+
type: optionsType) else {
126142
return
127143
}
128144

@@ -143,7 +159,7 @@ extension RerouteController: RerouteObserver {
143159
func onRerouteReceived(forRouteResponse routeResponse: String, routeRequest: String, origin: RouterOrigin) {
144160
guard reroutesProactively else { return }
145161

146-
guard let decodedRequest = Self.decode(routeRequest: routeRequest) else {
162+
guard let decodedRequest = Self.decode(routeRequest: routeRequest, type: optionsType) else {
147163
delegate?.rerouteControllerDidFailToReroute(self, with: DirectionsError.invalidResponse(nil))
148164
return
149165
}
@@ -191,17 +207,31 @@ extension RerouteController: RerouteObserver {
191207
}
192208

193209
extension RerouteController {
194-
static internal func decode(routeRequest: String, routeResponse: DataRef) -> (routeOptions: RouteOptions, routeResponse: RouteResponse)? {
210+
internal func decode(routeRequest: String, routeResponse: DataRef)
211+
-> (routeOptions: RouteOptions, routeResponse: RouteResponse)? {
212+
Self.decode(routeRequest: routeRequest, routeResponse: routeResponse, type: optionsType)
213+
}
214+
215+
static internal func decode(
216+
routeRequest: String,
217+
routeResponse: DataRef,
218+
type: RouteOptions.Type
219+
) -> (routeOptions: RouteOptions, routeResponse: RouteResponse)? {
195220
var result: (routeOptions: RouteOptions, routeResponse: RouteResponse)?
196221
routeResponse.withData { responseData in
197222
result = decode(routeRequest: routeRequest,
198-
routeResponse: responseData)
223+
routeResponse: responseData,
224+
type: type)
199225
}
200226
return result
201227
}
202228

203-
static internal func decode(routeRequest: String, routeResponse: Data) -> (routeOptions: RouteOptions, routeResponse: RouteResponse)? {
204-
guard let decodedRequest = decode(routeRequest: routeRequest),
229+
static internal func decode(
230+
routeRequest: String,
231+
routeResponse: Data,
232+
type: RouteOptions.Type
233+
) -> (routeOptions: RouteOptions, routeResponse: RouteResponse)? {
234+
guard let decodedRequest = decode(routeRequest: routeRequest, type: type),
205235
let decodedResponse = decode(routeResponse: routeResponse,
206236
routeOptions: decodedRequest.routeOptions,
207237
credentials: decodedRequest.credentials) else {
@@ -211,9 +241,12 @@ extension RerouteController {
211241
return (decodedRequest.routeOptions, decodedResponse)
212242
}
213243

214-
static internal func decode(routeRequest: String) -> (routeOptions: RouteOptions, credentials: Credentials)? {
244+
static internal func decode(
245+
routeRequest: String,
246+
type: RouteOptions.Type
247+
) -> (routeOptions: RouteOptions, credentials: Credentials)? {
215248
guard let requestURL = URL(string: routeRequest),
216-
let routeOptions = RouteOptions(url: requestURL) else {
249+
let routeOptions = decodeRouteOptions(with: routeRequest, type: type) else {
217250
return nil
218251
}
219252

@@ -231,6 +264,14 @@ extension RerouteController {
231264
return try? decoder.decode(RouteResponse.self,
232265
from: routeResponse)
233266
}
267+
268+
static func decodeRouteOptions(
269+
with routeRequest: String,
270+
type: RouteOptions.Type
271+
) -> RouteOptions? {
272+
let url = URL(string: routeRequest)
273+
return url?.routeOptions(with: type)
274+
}
234275
}
235276

236277
extension RerouteController: RerouteControllerInterface {
@@ -246,13 +287,13 @@ extension RerouteController: RerouteControllerInterface {
246287
type: .routerError)))
247288
return
248289
}
249-
250-
guard let routeOptions = RouteOptions(url: URL(string: url)!) else {
290+
291+
guard let routeOptions = options(with: url) else {
251292
callback(.init(error: RerouteError(message: "Unable to decode route request for rerouting.",
252293
type: .routerError)))
253294
return
254295
}
255-
296+
256297
reroutingRequest = customRoutingProvider.calculateRoutes(options: routeOptions) { [weak self] result in
257298
guard let self = self else { return }
258299

@@ -281,3 +322,15 @@ extension RerouteController: RerouteControllerInterface {
281322
reroutingRequest?.cancel()
282323
}
283324
}
325+
326+
extension URL {
327+
func routeOptions(with type: RouteOptions.Type) -> RouteOptions? {
328+
guard let baseOptions = RouteOptions(url: self) else {
329+
return nil
330+
}
331+
let profileIdentifier = baseOptions.profileIdentifier
332+
let waypoints = baseOptions.waypoints
333+
let queryItems = URLComponents(url: self, resolvingAgainstBaseURL: true)?.queryItems
334+
return type.init(waypoints: waypoints, profileIdentifier: profileIdentifier, queryItems: queryItems)
335+
}
336+
}

Sources/MapboxCoreNavigation/RouteController.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ open class RouteController: NSObject {
291291
completion?(.failure(RouteControllerError.failedToSerializeRoute))
292292
return
293293
}
294+
let routeOptionsType = indexedRouteResponse.routeOptionsType
294295
sharedNavigator.setRoutes(routesData,
295296
uuid: sessionUUID,
296297
legIndex: UInt32(legIndex),
@@ -302,7 +303,8 @@ open class RouteController: NSObject {
302303
case .success(let info):
303304
let alternativeRoutes = info.1.compactMap {
304305
AlternativeRoute(mainRoute: newMainRoute,
305-
alternativeRoute: $0)
306+
alternativeRoute: $0,
307+
routeOptionsType: routeOptionsType)
306308
}
307309
let alerts = routesData.primaryRoute().getRouteInfo().alerts
308310
self.routeAlerts = alerts.reduce(into: [:]) { dictionary, alert in
@@ -711,6 +713,7 @@ open class RouteController: NSObject {
711713
private func commonInit(customRoutingProvider: RoutingProvider?, options: RouteOptions) {
712714
UIDevice.current.isBatteryMonitoringEnabled = true
713715
navigatorType.datasetProfileIdentifier = options.profileIdentifier
716+
rerouteController.set(initialOptions: options)
714717

715718
if let customRoutingProvider = customRoutingProvider {
716719
self.customRoutingProvider = customRoutingProvider
@@ -1088,7 +1091,8 @@ extension RouteController {
10881091
var removedRoutes = continuousAlternatives.filter {
10891092
removedIds.contains($0.id)
10901093
}
1091-
1094+
1095+
let routeOptionsType = indexedRouteResponse.routeOptionsType
10921096
self.sharedNavigator.setAlternativeRoutes(with: alternatives.map(\.route),
10931097
completion: { [weak self] result in
10941098
guard let self = self else { return }
@@ -1097,7 +1101,8 @@ extension RouteController {
10971101
case .success(let routeAlternatives):
10981102
let alternativeRoutes = routeAlternatives.compactMap {
10991103
AlternativeRoute(mainRoute: self.route,
1100-
alternativeRoute: $0)
1104+
alternativeRoute: $0,
1105+
routeOptionsType: routeOptionsType)
11011106
}
11021107

11031108
removedRoutes.append(contentsOf: alternatives.filter { alternative in
@@ -1106,7 +1111,8 @@ extension RouteController {
11061111
})
11071112
}.compactMap {
11081113
AlternativeRoute(mainRoute: self.route,
1109-
alternativeRoute: $0)
1114+
alternativeRoute: $0,
1115+
routeOptionsType: routeOptionsType)
11101116
})
11111117
self.continuousAlternatives = alternativeRoutes
11121118
self.report(newAlternativeRoutes: alternativeRoutes,
@@ -1162,7 +1168,7 @@ extension RouteController {
11621168
let onlineRoute = userInfo[Navigator.NotificationUserInfoKey.coincideOnlineRouteKey] as? RouteInterface else {
11631169
return
11641170
}
1165-
guard let decoded = RerouteController.decode(routeRequest: onlineRoute.getRequestUri(),
1171+
guard let decoded = rerouteController.decode(routeRequest: onlineRoute.getRequestUri(),
11661172
routeResponse: onlineRoute.getResponseJsonRef()) else {
11671173
return
11681174
}

Sources/MapboxCoreNavigation/Router.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ public struct IndexedRouteResponse {
4949
let routesData = routesData(routeParserType: RouteParser.self) else {
5050
return []
5151
}
52-
52+
53+
let routeOptionsType = self.routeOptionsType
5354
let alternatives = routesData.alternativeRoutes().compactMap {
5455
AlternativeRoute(mainRoute: mainRoute,
55-
alternativeRoute: $0)
56+
alternativeRoute: $0,
57+
routeOptionsType: routeOptionsType)
5658
}
5759
return alternatives
5860
}
@@ -116,6 +118,10 @@ public struct IndexedRouteResponse {
116118
return options
117119
}
118120
}
121+
122+
var routeOptionsType: RouteOptions.Type {
123+
type(of: validatedRouteOptions)
124+
}
119125
}
120126

121127
/**

0 commit comments

Comments
 (0)