From 908f1a70f7ef33df2e8549f3623b280cf40c9936 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 21 May 2024 13:22:55 -0700 Subject: [PATCH 1/8] use maplibre style rather than mapbox style --- MapboxNavigation/DayStyle.swift | 6 +-- MapboxNavigation/MLNStyle.swift | 74 --------------------------------- MapboxNavigation/Style.swift | 8 ++-- 3 files changed, 7 insertions(+), 81 deletions(-) delete mode 100644 MapboxNavigation/MLNStyle.swift diff --git a/MapboxNavigation/DayStyle.swift b/MapboxNavigation/DayStyle.swift index 20c6acbf..36722659 100644 --- a/MapboxNavigation/DayStyle.swift +++ b/MapboxNavigation/DayStyle.swift @@ -47,7 +47,7 @@ private extension UIFont { open class DayStyle: Style { public required init() { super.init() - mapStyleURL = MLNStyle.navigationGuidanceDayStyleURL + mapStyleURL = MLNStyle.defaultStyle().url styleType = .day statusBarStyle = .default } @@ -168,8 +168,8 @@ open class DayStyle: Style { open class NightStyle: DayStyle { public required init() { super.init() - mapStyleURL = MLNStyle.navigationGuidanceNightStyleURL - previewMapStyleURL = MLNStyle.navigationPreviewNightStyleURL + mapStyleURL = MLNStyle.defaultStyle().url + previewMapStyleURL = MLNStyle.defaultStyle().url styleType = .night statusBarStyle = .lightContent } diff --git a/MapboxNavigation/MLNStyle.swift b/MapboxNavigation/MLNStyle.swift deleted file mode 100644 index 2bc90056..00000000 --- a/MapboxNavigation/MLNStyle.swift +++ /dev/null @@ -1,74 +0,0 @@ -import Foundation -import MapLibre - -public extension MLNStyle { - // The Mapbox China Day Style URL. - internal static let mapboxChinaDayStyleURL = URL(string: "mapbox://styles/mapbox/streets-zh-v1")! - - // The Mapbox China Night Style URL. - internal static let mapboxChinaNightStyleURL = URL(string: "mapbox://styles/mapbox/dark-zh-v1")! - - /** - Returns the URL to the current version of the Mapbox Navigation Guidance Day style. - */ - @objc class var navigationGuidanceDayStyleURL: URL { - URL(string: "mapbox://styles/mapbox/navigation-guidance-day-v4")! - } - - /** - Returns the URL to the current version of the Mapbox Navigation Guidance Night style. - */ - @objc class var navigationGuidanceNightStyleURL: URL { - URL(string: "mapbox://styles/mapbox/navigation-guidance-night-v4")! - } - - /** - Returns the URL to the given version of the navigation guidance style. Available version are 1, 2, 3, and 4. - - We only have one version of navigation guidance style in China, so if you switch your endpoint to .cn, it will return the default day style. - */ - @objc class func navigationGuidanceDayStyleURL(version: Int) -> URL { - URL(string: "mapbox://styles/mapbox/navigation-guidance-day-v\(version)")! - } - - /** - Returns the URL to the given version of the navigation guidance style. Available version are 2, 3, and 4. - - We only have one version of navigation guidance style in China, so if you switch your endpoint to .cn, it will return the default night style. - */ - @objc class func navigationGuidanceNightStyleURL(version: Int) -> URL { - URL(string: "mapbox://styles/mapbox/navigation-guidance-night-v\(version)")! - } - - /** - Returns the URL to the current version of the Mapbox Navigation Preview Day style. - */ - @objc class var navigationPreviewDayStyleURL: URL { - URL(string: "mapbox://styles/mapbox/navigation-preview-day-v4")! - } - - /** - Returns the URL to the current version of the Mapbox Navigation Preview Night style. - */ - @objc class var navigationPreviewNightStyleURL: URL { - URL(string: "mapbox://styles/mapbox/navigation-preview-night-v4")! - } - - /** - Returns the URL to the given version of the Mapbox Navigation Preview Day style. Available versions are 1, 2, 3, and 4. - - We only have one version of Navigation Preview style in China, so if you switch your endpoint to .cn, it will return the default day style. - */ - @objc class func navigationPreviewDayStyleURL(version: Int) -> URL { - URL(string: "mapbox://styles/mapbox/navigation-guidance-day-v\(version)")! - } - - /** - Returns the URL to the given version of the Mapbox Navigation Preview Night style. Available versions are 2, 3, and 4. - - We only have one version of Navigation Preview style in China, so if you switch your endpoint to .cn, it will return the default night style. - */ - @objc class func navigationPreviewNightStyleURL(version: Int) -> URL { - URL(string: "mapbox://styles/mapbox/navigation-guidance-night-v\(version)")! - } -} diff --git a/MapboxNavigation/Style.swift b/MapboxNavigation/Style.swift index 5d816a23..5b4e7d78 100644 --- a/MapboxNavigation/Style.swift +++ b/MapboxNavigation/Style.swift @@ -34,20 +34,20 @@ open class Style: NSObject { /** URL of the style to display on the map during turn-by-turn navigation. */ - @objc open var mapStyleURL: URL = MLNStyle.navigationGuidanceDayStyleURL - + @objc open var mapStyleURL: URL = MLNStyle.defaultStyle().url + #if canImport(CarPlay) /** URL of the style to display on the map when previewing a route, for example on CarPlay. */ - @objc open var previewMapStyleURL = MLNStyle.navigationPreviewDayStyleURL + @objc open var previewMapStyleURL = MLNStyle.defaultStyle().url #else /** URL of the style to display on the map when previewing a route. This property is currently unused by default, but you can use it to present your own route preview map. */ - @objc open var previewMapStyleURL = MLNStyle.navigationPreviewDayStyleURL + @objc open var previewMapStyleURL = MLNStyle.defaultStyle().url #endif /** From 9c5b6370143fa99d228bb98af3b6758b2cd84fa4 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 21 May 2024 16:17:28 -0700 Subject: [PATCH 2/8] docs for NavigationViewController.init --- .../NavigationViewController.swift | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index 7dc06535..38bafc66 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -345,11 +345,23 @@ open class NavigationViewController: UIViewController { super.init(coder: aDecoder) } - /** - Initializes a `NavigationViewController` that provides turn by turn navigation for the given route. A optional `direction` object is needed for potential rerouting. - - See [Mapbox Directions](https://mapbox.github.io/mapbox-navigation-ios/directions/) for further information. - */ + /// Initializes a `NavigationViewController` that provides turn by turn navigation for the given route. A optional `directions` object is needed for potential rerouting. + /// + /// ``` + /// var dayStyle = DayStyle() + /// dayStyle.mapStyleURL = styleURL + /// let vc = NavigationViewController(route: route, styles: [dayStyle]) + /// self.presentViewController(vc, animated: true) + /// ``` + /// - Parameters: + /// - route: The route to follow. + /// - directions: Used when recomputing a new route, for example if the user takes a wrong turn and needs re-routing. + /// - styles: The `[dayStyle]` or `[dayStyle, nightStyle]` styles used to render the map. If nil, the default styles will be used. + /// - routeController: Used to monitor the route and notify of changes to the route. If nil, a default will be used. + /// - locationManager: Tracks the users location along the route. If nil, a default will be used. + /// - voiceController: Produces voice instructions for route navigation. If nil, a default will be used. + /// + /// See [Mapbox Directions](https://mapbox.github.io/mapbox-navigation-ios/directions/) for further information. @objc(initWithRoute:directions:styles:routeController:locationManager:voiceController:) public required init(for route: Route, directions: Directions = Directions.shared, From 8ff89c1adec8a9b0ab4c24d5dbb500cebbb0f7d8 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 21 May 2024 16:24:53 -0700 Subject: [PATCH 3/8] Deprecate default style, instead pass in style URL --- .../CarPlayMapViewController.swift | 4 +- .../CarPlayNavigationViewController.swift | 4 +- MapboxNavigation/DayStyle.swift | 13 ++- MapboxNavigation/NavigationView.swift | 2 +- .../NavigationViewController.swift | 85 ++++++++++++++++--- MapboxNavigation/Style.swift | 28 +++++- .../Tests/NavigationViewControllerTests.swift | 39 +++++---- 7 files changed, 132 insertions(+), 43 deletions(-) diff --git a/MapboxNavigation/CarPlayMapViewController.swift b/MapboxNavigation/CarPlayMapViewController.swift index 79e4a6a7..4de78ece 100644 --- a/MapboxNavigation/CarPlayMapViewController.swift +++ b/MapboxNavigation/CarPlayMapViewController.swift @@ -50,8 +50,8 @@ class CarPlayMapViewController: UIViewController, MLNMapViewDelegate { super.viewDidLoad() self.styleManager = StyleManager(self) - self.styleManager.styles = [DayStyle(), NightStyle()] - + self.styleManager.styles = [DayStyle(demoStyle: ()), NightStyle(demoStyle: ())] + self.resetCamera(animated: false, altitude: CarPlayMapViewController.defaultAltitude) self.mapView.setUserTrackingMode(.followWithCourse, animated: true, completionHandler: nil) } diff --git a/MapboxNavigation/CarPlayNavigationViewController.swift b/MapboxNavigation/CarPlayNavigationViewController.swift index 7789e380..b7789fef 100644 --- a/MapboxNavigation/CarPlayNavigationViewController.swift +++ b/MapboxNavigation/CarPlayNavigationViewController.swift @@ -85,8 +85,8 @@ public class CarPlayNavigationViewController: UIViewController, MLNMapViewDelega view.addSubview(mapView) self.styleManager = StyleManager(self) - self.styleManager.styles = [DayStyle(), NightStyle()] - + self.styleManager.styles = [DayStyle(demoStyle: ()), NightStyle(demoStyle: ())] + self.resumeNotifications() self.routeController.resume() mapView.recenterMap() diff --git a/MapboxNavigation/DayStyle.swift b/MapboxNavigation/DayStyle.swift index 36722659..87066d09 100644 --- a/MapboxNavigation/DayStyle.swift +++ b/MapboxNavigation/DayStyle.swift @@ -45,13 +45,12 @@ private extension UIFont { */ @objc(MBDayStyle) open class DayStyle: Style { - public required init() { - super.init() - mapStyleURL = MLNStyle.defaultStyle().url + @objc public required init(mapStyleURL: URL) { + super.init(mapStyleURL: mapStyleURL) styleType = .day statusBarStyle = .default } - + override open func apply() { super.apply() @@ -166,10 +165,8 @@ open class DayStyle: Style { */ @objc(MBNightStyle) open class NightStyle: DayStyle { - public required init() { - super.init() - mapStyleURL = MLNStyle.defaultStyle().url - previewMapStyleURL = MLNStyle.defaultStyle().url + public required init(mapStyleURL: URL) { + super.init(mapStyleURL: mapStyleURL) styleType = .night statusBarStyle = .lightContent } diff --git a/MapboxNavigation/NavigationView.swift b/MapboxNavigation/NavigationView.swift index 007839f9..ca47ecc4 100644 --- a/MapboxNavigation/NavigationView.swift +++ b/MapboxNavigation/NavigationView.swift @@ -210,7 +210,7 @@ open class NavigationView: UIView { override open func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() - DayStyle().apply() + DayStyle(demoStyle: ()).apply() [self.mapView, self.instructionsBannerView, self.lanesView, self.bottomBannerView, self.nextBannerView].forEach { $0.prepareForInterfaceBuilder() } self.wayNameView.text = "Street Label" } diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index 38bafc66..e3fd2350 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -345,32 +345,97 @@ open class NavigationViewController: UIViewController { super.init(coder: aDecoder) } - /// Initializes a `NavigationViewController` that provides turn by turn navigation for the given route. A optional `directions` object is needed for potential rerouting. + /// Initializes a `NavigationViewController` that provides turn by turn navigation for the given route. /// /// ``` - /// var dayStyle = DayStyle() - /// dayStyle.mapStyleURL = styleURL + /// let dayStyle = DayStyle(mapStyleURL: styleURL) /// let vc = NavigationViewController(route: route, styles: [dayStyle]) /// self.presentViewController(vc, animated: true) /// ``` /// - Parameters: /// - route: The route to follow. - /// - directions: Used when recomputing a new route, for example if the user takes a wrong turn and needs re-routing. + /// - directions: Used when recomputing a new route, for example if the user takes a wrong turn and needs re-routing. If unspecified, a default will be used. /// - styles: The `[dayStyle]` or `[dayStyle, nightStyle]` styles used to render the map. If nil, the default styles will be used. /// - routeController: Used to monitor the route and notify of changes to the route. If nil, a default will be used. /// - locationManager: Tracks the users location along the route. If nil, a default will be used. /// - voiceController: Produces voice instructions for route navigation. If nil, a default will be used. /// /// See [Mapbox Directions](https://mapbox.github.io/mapbox-navigation-ios/directions/) for further information. + @available(*, deprecated, message: "Use `init(for:directions:dayStyle:...) or init(for:directions:dayStyleURL:...)` instead.") @objc(initWithRoute:directions:styles:routeController:locationManager:voiceController:) + public convenience init(for route: Route, + directions: Directions = Directions.shared, + styles: [Style]? = [DayStyle(), NightStyle()], + routeController: RouteController? = nil, + locationManager: NavigationLocationManager? = nil, + voiceController: RouteVoiceController? = nil) { + let styles = styles ?? [] + assert(styles.count <= 2, "Having more than two styles is undefined.") + let dayStyle = styles.first ?? DayStyle(demoStyle: ()) + let nightStyle = styles.count > 1 ? styles[1] : NightStyle(mapStyleURL: dayStyle.mapStyleURL) + + self.init(for: route, dayStyle: dayStyle, nightStyle: nightStyle, directions: directions, routeController: routeController, locationManager: locationManager, voiceController: voiceController) + } + + /// Initializes a `NavigationViewController` that provides turn by turn navigation for the given route. + /// + /// - Parameters: + /// - route: The route to follow. + /// - dayStyleURL: URL for the style rules used to render the map during daylight hours. + /// - nightStyleURL: URL for the style rules used to render the map during nighttime hours. If nil, `dayStyleURL` will be used at night as well. + /// - directions: Used when recomputing a new route, for example if the user takes a wrong turn and needs re-routing. If unspecified, a default will be used. + /// - routeController: Used to monitor the route and notify of changes to the route. If nil, a default will be used. + /// - locationManager: Tracks the users location along the route. If nil, a default will be used. + /// - voiceController: Produces voice instructions for route navigation. If nil, a default will be used. + /// + /// See [Mapbox Directions](https://mapbox.github.io/mapbox-navigation-ios/directions/) for further information. + @objc(initWithRoute:dayStyleURL:nightStyleURL:directions:routeController:locationManager:voiceController:) + public convenience init(for route: Route, + dayStyleURL: URL, + nightStyleURL: URL? = nil, + directions: Directions = Directions.shared, + routeController: RouteController? = nil, + locationManager: NavigationLocationManager? = nil, + voiceController: RouteVoiceController? = nil) { + let dayStyle = DayStyle(mapStyleURL: dayStyleURL) + let nightStyle = NightStyle(mapStyleURL: nightStyleURL ?? dayStyleURL) + self.init(for: route, dayStyle: dayStyle, nightStyle: nightStyle, directions: directions, routeController: routeController, locationManager: locationManager, voiceController: voiceController) + } + + /// Initializes a `NavigationViewController` that provides turn by turn navigation for the given route. + /// + /// - Parameters: + /// - route: The route to follow. + /// - dayStyle: Style used to render the map during daylight hours. + /// - nightStyle: Style used to render the map during nighttime hours. If nil, `dayStyle` will be used at night as well. + /// - directions: Used when recomputing a new route, for example if the user takes a wrong turn and needs re-routing. If unspecified, a default will be used. + /// - routeController: Used to monitor the route and notify of changes to the route. If nil, a default will be used. + /// - locationManager: Tracks the users location along the route. If nil, a default will be used. + /// - voiceController: Produces voice instructions for route navigation. If nil, a default will be used. + /// + /// See [Mapbox Directions](https://mapbox.github.io/mapbox-navigation-ios/directions/) for further information. + @objc(initWithRoute:dayStyle:nightStyle:directions:routeController:locationManager:voiceController:) public required init(for route: Route, + dayStyle: Style, + nightStyle: Style? = nil, directions: Directions = Directions.shared, - styles: [Style]? = [DayStyle(), NightStyle()], routeController: RouteController? = nil, locationManager: NavigationLocationManager? = nil, voiceController: RouteVoiceController? = nil) { + let nightStyle = { + if let nightStyle { + return nightStyle + } + + let dayCopy: Style = dayStyle.copy() as! Style + dayCopy.styleType = .night + return dayCopy + }() + + assert(dayStyle.styleType == .day) + assert(nightStyle.styleType == .night) + super.init(nibName: nil, bundle: nil) - self.locationManager = locationManager ?? NavigationLocationManager() let routeController = routeController ?? RouteController(along: route, directions: directions, locationManager: self.locationManager) self.routeController = routeController @@ -399,8 +464,8 @@ open class NavigationViewController: UIViewController { mapViewController.reportButton.isHidden = !self.showsReportFeedback self.styleManager = StyleManager(self) - self.styleManager.styles = styles ?? [DayStyle(), NightStyle()] - + self.styleManager.styles = [dayStyle, nightStyle] + if !(route.routeOptions is NavigationRouteOptions) { print("`Route` was created using `RouteOptions` and not `NavigationRouteOptions`. Although not required, this may lead to a suboptimal navigation experience. Without `NavigationRouteOptions`, it is not guaranteed you will get congestion along the route line, better ETAs and ETA label color dependent on congestion.") } @@ -527,8 +592,8 @@ open class NavigationViewController: UIViewController { let locationManager = routeController.locationManager.copy() as! NavigationLocationManager let directions = routeController.directions let route = routeController.routeProgress.route - let navigationViewController = NavigationViewController(for: route, directions: directions, routeController: routeController, locationManager: locationManager) - + let navigationViewController = NavigationViewController(for: route, dayStyle: DayStyle(demoStyle: ()), directions: directions, routeController: routeController, locationManager: locationManager) + window.rootViewController?.topMostViewController()?.present(navigationViewController, animated: true, completion: { navigationViewController.isUsedInConjunctionWithCarPlayWindow = true }) diff --git a/MapboxNavigation/Style.swift b/MapboxNavigation/Style.swift index 5b4e7d78..4ac532e6 100644 --- a/MapboxNavigation/Style.swift +++ b/MapboxNavigation/Style.swift @@ -54,8 +54,32 @@ open class Style: NSObject { Applies the style for all changed properties. */ @objc open func apply() {} - - @objc override public required init() {} + + @available(*, deprecated, message: "Use `init(mapStyleURL:)` to specify your map style. If you want to try the demo maplibre tiles, use init(demoStyle: ()).") + @objc override public convenience init() { + self.init(demoStyle: ()) + } + + @objc public required init(mapStyleURL: URL) { + self.mapStyleURL = mapStyleURL + } + + @objc public convenience init(demoStyle: ()) { + self.init(mapStyleURL: MLNStyle.defaultStyle().url) + } +} + +extension Style: NSCopying { + public func copy(with zone: NSZone? = nil) -> Any { + let copy = Self(mapStyleURL: self.mapStyleURL) + copy.tintColor = self.tintColor + copy.statusBarStyle = self.statusBarStyle + copy.fontFamily = self.fontFamily + copy.styleType = self.styleType + copy.mapStyleURL = self.mapStyleURL + copy.previewMapStyleURL = self.previewMapStyleURL + return copy + } } /** diff --git a/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift b/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift index 5253487c..273c9e90 100644 --- a/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift +++ b/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift @@ -17,6 +17,7 @@ class NavigationViewControllerTests: XCTestCase { lazy var dependencies: (navigationViewController: NavigationViewController, startLocation: CLLocation, poi: [CLLocation], endLocation: CLLocation, voice: RouteVoiceController) = { let voice = FakeVoiceController() let nav = NavigationViewController(for: initialRoute, + dayStyle: DayStyle(demoStyle: ()), directions: Directions(accessToken: "garbage", host: nil), voiceController: voice) @@ -88,7 +89,10 @@ class NavigationViewControllerTests: XCTestCase { } func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceMoreThanOnceWithOneStyle() { - let navigationViewController = NavigationViewController(for: initialRoute, directions: fakeDirections, styles: [DayStyle()], voiceController: FakeVoiceController()) + let navigationViewController = NavigationViewController(for: initialRoute, + dayStyle: DayStyle(demoStyle: ()), + directions: fakeDirections, + voiceController: FakeVoiceController()) let routeController = navigationViewController.routeController! navigationViewController.styleManager.delegate = self @@ -104,7 +108,9 @@ class NavigationViewControllerTests: XCTestCase { // If tunnel flags are enabled and we need to switch styles, we should not force refresh the map style because we have only 1 style. func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceWhenOnlyOneStyle() { - let navigationViewController = NavigationViewController(for: initialRoute, directions: fakeDirections, styles: [NightStyle()], voiceController: FakeVoiceController()) + // REVIEW: is this right? Does it make sense that there would ever be *only* a night style? + // let navigationViewController = NavigationViewController(for: initialRoute, directions: fakeDirections, styles: [NightStyle()], voiceController: FakeVoiceController()) + let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), directions: fakeDirections, voiceController: FakeVoiceController()) let routeController = navigationViewController.routeController! navigationViewController.styleManager.delegate = self @@ -119,7 +125,7 @@ class NavigationViewControllerTests: XCTestCase { } func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceMoreThanOnceWithTwoStyles() { - let navigationViewController = NavigationViewController(for: initialRoute, directions: fakeDirections, styles: [DayStyle(), NightStyle()], voiceController: FakeVoiceController()) + let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), nightStyle: NightStyle(demoStyle: ()), directions: fakeDirections, voiceController: FakeVoiceController()) let routeController = navigationViewController.routeController! navigationViewController.styleManager.delegate = self @@ -173,8 +179,8 @@ class NavigationViewControllerTests: XCTestCase { func testDestinationAnnotationUpdatesUponReroute() { let styleLoaded = XCTestExpectation(description: "Style Loaded") - let navigationViewController = NavigationViewControllerTestable(for: initialRoute, styles: [TestableDayStyle()], styleLoaded: styleLoaded) - + let navigationViewController = NavigationViewControllerTestable(for: initialRoute, dayStyle: DayStyle.blankStyleForTesting, styleLoaded: styleLoaded) + // wait for the style to load -- routes won't show without it. wait(for: [styleLoaded], timeout: 5) navigationViewController.route = self.initialRoute @@ -248,21 +254,19 @@ private extension NavigationViewControllerTests { class NavigationViewControllerTestable: NavigationViewController { var styleLoadedExpectation: XCTestExpectation - + required init(for route: Route, - directions: Directions = Directions(accessToken: "abc", host: ""), - styles: [Style]? = [DayStyle(), NightStyle()], - locationManager: NavigationLocationManager? = NavigationLocationManager(), + dayStyle: Style, styleLoaded: XCTestExpectation) { self.styleLoadedExpectation = styleLoaded - super.init(for: route, directions: directions, styles: styles, locationManager: locationManager, voiceController: FakeVoiceController()) + super.init(for: route, dayStyle: dayStyle, directions: Directions(accessToken: "abc", host: ""), voiceController: FakeVoiceController()) } - @objc(initWithRoute:directions:styles:routeController:locationManager:voiceController:) - required init(for route: Route, directions: Directions, styles: [Style]?, routeController: RouteController?, locationManager: NavigationLocationManager?, voiceController: RouteVoiceController?) { - fatalError("init(for:directions:styles:routeController:locationManager:voiceController:) is not supported in this testing subclass.") + @objc(initWithRoute:dayStyle:nightStyle:directions:routeController:locationManager:voiceController:) + required init(for route: Route, dayStyle: Style, nightStyle: Style? = nil, directions: Directions = Directions.shared, routeController: RouteController? = nil, locationManager: NavigationLocationManager? = nil, voiceController: RouteVoiceController? = nil) { + fatalError("init(for:directions:dayStyle:nightStyle:routeController:locationManager:voiceController:) has not been implemented") } - + func mapView(_ mapView: MLNMapView, didFinishLoading style: MLNStyle) { self.styleLoadedExpectation.fulfill() } @@ -273,10 +277,9 @@ class NavigationViewControllerTestable: NavigationViewController { } } -class TestableDayStyle: DayStyle { - required init() { - super.init() - mapStyleURL = Fixture.blankStyle +extension DayStyle { + static var blankStyleForTesting: Self { + Self(mapStyleURL: Fixture.blankStyle) } } From 7d907bfebb2a46f24a51de40e211cbb2ac018755 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 22 May 2024 17:06:52 -0700 Subject: [PATCH 4/8] add notes about broken/useless tests --- .../Sources/Tests/NavigationViewControllerTests.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift b/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift index 273c9e90..496eaa42 100644 --- a/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift +++ b/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift @@ -28,6 +28,7 @@ class NavigationViewControllerTests: XCTestCase { let firstLocation = location(at: firstCoord) var poi = [CLLocation]() + // REVIEW: What are these variable names? They seem completely unrelated to the intersections in the route. let taylorStreetIntersection = routeController.routeProgress.route.legs.first!.steps.first!.intersections!.first! let turkStreetIntersection = routeController.routeProgress.route.legs.first!.steps[3].intersections!.first! let fultonStreetIntersection = routeController.routeProgress.route.legs.first!.steps[5].intersections!.first! @@ -88,6 +89,7 @@ class NavigationViewControllerTests: XCTestCase { XCTAssertFalse(wayNameView.isHidden, "WayNameView should be visible.") } + // TODO: This test doesn't seem to be testing anything. Adding a test where `updatedStyleNumberOfTimes = 1` might be illuminating func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceMoreThanOnceWithOneStyle() { let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), @@ -98,6 +100,7 @@ class NavigationViewControllerTests: XCTestCase { let someLocation = self.dependencies.poi.first! + // TODO: Why are we updating with the same location 3 times? routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) @@ -106,16 +109,16 @@ class NavigationViewControllerTests: XCTestCase { self.updatedStyleNumberOfTimes = 0 } + // TODO: This test doesn't seem to be testing anything. The route does not actually go through a tunnel. // If tunnel flags are enabled and we need to switch styles, we should not force refresh the map style because we have only 1 style. func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceWhenOnlyOneStyle() { - // REVIEW: is this right? Does it make sense that there would ever be *only* a night style? - // let navigationViewController = NavigationViewController(for: initialRoute, directions: fakeDirections, styles: [NightStyle()], voiceController: FakeVoiceController()) let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), directions: fakeDirections, voiceController: FakeVoiceController()) let routeController = navigationViewController.routeController! navigationViewController.styleManager.delegate = self let someLocation = self.dependencies.poi.first! + // TODO: Why are we updating with the same location 3 times? routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) @@ -124,6 +127,8 @@ class NavigationViewControllerTests: XCTestCase { self.updatedStyleNumberOfTimes = 0 } + // TODO: This test doesn't seem to be testing anything. The route does not actually go through a tunnel or do anything + // that would cause the style to change. Maybe having a positive test where the style *does* change exactly once would be helpful func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceMoreThanOnceWithTwoStyles() { let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), nightStyle: NightStyle(demoStyle: ()), directions: fakeDirections, voiceController: FakeVoiceController()) let routeController = navigationViewController.routeController! @@ -131,6 +136,7 @@ class NavigationViewControllerTests: XCTestCase { let someLocation = self.dependencies.poi.first! + // TODO: Why are we updating with the same location 3 times? routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) From 708832e677e67501d218b7e29ce17eca0aff591a Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 22 May 2024 17:15:44 -0700 Subject: [PATCH 5/8] fixup! Deprecate default style, instead pass in style URL --- MapboxNavigation/NavigationViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index e3fd2350..805dd0c3 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -361,7 +361,7 @@ open class NavigationViewController: UIViewController { /// - voiceController: Produces voice instructions for route navigation. If nil, a default will be used. /// /// See [Mapbox Directions](https://mapbox.github.io/mapbox-navigation-ios/directions/) for further information. - @available(*, deprecated, message: "Use `init(for:directions:dayStyle:...) or init(for:directions:dayStyleURL:...)` instead.") + @available(*, deprecated, message: "Use `init(for:dayStyle:...) or init(for:dayStyleURL:...)` instead.") @objc(initWithRoute:directions:styles:routeController:locationManager:voiceController:) public convenience init(for route: Route, directions: Directions = Directions.shared, From 44f15c259e483faa4e87bdf6b373977be1cd4bb4 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 24 May 2024 09:49:33 -0700 Subject: [PATCH 6/8] Revert "add notes about broken/useless tests" This reverts commit 7d907bfebb2a46f24a51de40e211cbb2ac018755. --- .../Sources/Tests/NavigationViewControllerTests.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift b/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift index 496eaa42..a9d1e9ec 100644 --- a/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift +++ b/MapboxNavigationTests/Sources/Tests/NavigationViewControllerTests.swift @@ -28,7 +28,6 @@ class NavigationViewControllerTests: XCTestCase { let firstLocation = location(at: firstCoord) var poi = [CLLocation]() - // REVIEW: What are these variable names? They seem completely unrelated to the intersections in the route. let taylorStreetIntersection = routeController.routeProgress.route.legs.first!.steps.first!.intersections!.first! let turkStreetIntersection = routeController.routeProgress.route.legs.first!.steps[3].intersections!.first! let fultonStreetIntersection = routeController.routeProgress.route.legs.first!.steps[5].intersections!.first! @@ -89,7 +88,6 @@ class NavigationViewControllerTests: XCTestCase { XCTAssertFalse(wayNameView.isHidden, "WayNameView should be visible.") } - // TODO: This test doesn't seem to be testing anything. Adding a test where `updatedStyleNumberOfTimes = 1` might be illuminating func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceMoreThanOnceWithOneStyle() { let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), @@ -100,7 +98,6 @@ class NavigationViewControllerTests: XCTestCase { let someLocation = self.dependencies.poi.first! - // TODO: Why are we updating with the same location 3 times? routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) @@ -109,7 +106,6 @@ class NavigationViewControllerTests: XCTestCase { self.updatedStyleNumberOfTimes = 0 } - // TODO: This test doesn't seem to be testing anything. The route does not actually go through a tunnel. // If tunnel flags are enabled and we need to switch styles, we should not force refresh the map style because we have only 1 style. func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceWhenOnlyOneStyle() { let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), directions: fakeDirections, voiceController: FakeVoiceController()) @@ -118,7 +114,6 @@ class NavigationViewControllerTests: XCTestCase { let someLocation = self.dependencies.poi.first! - // TODO: Why are we updating with the same location 3 times? routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) @@ -127,8 +122,6 @@ class NavigationViewControllerTests: XCTestCase { self.updatedStyleNumberOfTimes = 0 } - // TODO: This test doesn't seem to be testing anything. The route does not actually go through a tunnel or do anything - // that would cause the style to change. Maybe having a positive test where the style *does* change exactly once would be helpful func testNavigationShouldNotCallStyleManagerDidRefreshAppearanceMoreThanOnceWithTwoStyles() { let navigationViewController = NavigationViewController(for: initialRoute, dayStyle: DayStyle(demoStyle: ()), nightStyle: NightStyle(demoStyle: ()), directions: fakeDirections, voiceController: FakeVoiceController()) let routeController = navigationViewController.routeController! @@ -136,7 +129,6 @@ class NavigationViewControllerTests: XCTestCase { let someLocation = self.dependencies.poi.first! - // TODO: Why are we updating with the same location 3 times? routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) routeController.locationManager(routeController.locationManager, didUpdateLocations: [someLocation]) From 37e69c6484f12380c92554849447d5d45c0849e8 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 24 May 2024 10:04:17 -0700 Subject: [PATCH 7/8] undo formatting --- MapboxNavigation/DayStyle.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MapboxNavigation/DayStyle.swift b/MapboxNavigation/DayStyle.swift index 87066d09..d0f6dc55 100644 --- a/MapboxNavigation/DayStyle.swift +++ b/MapboxNavigation/DayStyle.swift @@ -50,7 +50,7 @@ open class DayStyle: Style { styleType = .day statusBarStyle = .default } - + override open func apply() { super.apply() From 945ddeeea3bdd3f0de2ac3dabeb50c2ddb19c6c1 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 24 May 2024 10:39:11 -0700 Subject: [PATCH 8/8] changelog entry --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e99120c2..014cb1a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,13 @@ - Updated MapLibre Native dependency to ios-v6.0.0 (https://github.com/maplibre/maplibre-native/releases/tag/ios-v6.0.0). Implementers need to change the prefix MGL to MLN for all MapLibre Native classes that are referenced. - Only snap location to route if the location is within the `RouteControllerUserLocationSnappingDistance` - Add support for Swift Package Manager while dropping Carthage and Cocoapods. + - Removed implicit default dependencies on MapBox tileservers by requiring explicit styles URLs in more places. + - Merged in . + - BREAKING: Removed `MLNStyle` extensions referencing non-functioning MapBox styles, e.g. `MLNStyle.navigationGuidanceDayStyleURL`. + - Added `Day/NightStyle(styleURL:)` which takes an explicit URL to a hosting tileserver style. + - Added `Day/NightStyle(demoStyle: ())` as an explicit alternative when the user doesn't have a tileserver handy. This uses MapLibre's demo style and is intended for testing and demonstration use only. + - Deprecated `DayStyle()`/`NightStyle()` initializers because they were backed by an implicit tile service. If these default styles *are* still used, they'll now use the MapLibre demo style. + - `NavigationViewController` now expects explicit style URLs with `NavigationViewController(route:dayStyleURL:nightStyleURL:...)` or NavigationViewController(route:dayStyle:nightStyle:...)` and the existing initializer, which allowed "default" styles, is deprecated and uses the MapLibre demo styles. ## v2.0.0 (May 23, 2023) - Upgrade minimum iOS version from 11.0 to 12.0.