Skip to content

Commit 4b337d8

Browse files
authored
Add new delegate methods to CarPlayManagerDelegate to be able to track when template is being presented or dismissed. Improve documentation. Minor styling changes. (#3219)
1 parent 5cbd69d commit 4b337d8

File tree

7 files changed

+194
-84
lines changed

7 files changed

+194
-84
lines changed

MapboxNavigation.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@
188188
8AAE94A126A60ADE00AA1127 /* CarPlayMapViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AAE94A026A60ADE00AA1127 /* CarPlayMapViewControllerDelegate.swift */; };
189189
8AB316C926BCA56D00C3AC76 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB316C826BCA56D00C3AC76 /* UIViewController.swift */; };
190190
8AB316CB26BCA72300C3AC76 /* CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB316CA26BCA72300C3AC76 /* CGSize.swift */; };
191+
8AB316A926BA026B00C3AC76 /* MapTemplateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB316A826BA026B00C3AC76 /* MapTemplateProvider.swift */; };
192+
8AB316AB26BA029100C3AC76 /* MapTemplateProviderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB316AA26BA029100C3AC76 /* MapTemplateProviderDelegate.swift */; };
191193
8ABB9E75268E0140009013A5 /* NavigationCameraTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ABB9E74268E0140009013A5 /* NavigationCameraTests.swift */; };
192194
8ABCD6A426AA0D9400B121B9 /* route-for-navigation-camera-bearing-smoothing.json in Resources */ = {isa = PBXBuildFile; fileRef = 8ABCD6A326AA0D9400B121B9 /* route-for-navigation-camera-bearing-smoothing.json */; };
193195
8AC3965325DC66570027A035 /* NavigationCameraType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AC3965225DC66570027A035 /* NavigationCameraType.swift */; };
@@ -668,6 +670,8 @@
668670
8AB316AE26BB315100C3AC76 /* CPMapTemplate+MBTestable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CPMapTemplate+MBTestable.m"; sourceTree = "<group>"; };
669671
8AB316C826BCA56D00C3AC76 /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
670672
8AB316CA26BCA72300C3AC76 /* CGSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGSize.swift; sourceTree = "<group>"; };
673+
8AB316A826BA026B00C3AC76 /* MapTemplateProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTemplateProvider.swift; sourceTree = "<group>"; };
674+
8AB316AA26BA029100C3AC76 /* MapTemplateProviderDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTemplateProviderDelegate.swift; sourceTree = "<group>"; };
671675
8ABB9E74268E0140009013A5 /* NavigationCameraTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCameraTests.swift; sourceTree = "<group>"; };
672676
8ABCD6A326AA0D9400B121B9 /* route-for-navigation-camera-bearing-smoothing.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "route-for-navigation-camera-bearing-smoothing.json"; sourceTree = "<group>"; };
673677
8AC3965225DC66570027A035 /* NavigationCameraType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCameraType.swift; sourceTree = "<group>"; };
@@ -1069,6 +1073,8 @@
10691073
8AAE94A026A60ADE00AA1127 /* CarPlayMapViewControllerDelegate.swift */,
10701074
C5FFAC1420D96F5B009E7F98 /* CarPlayNavigationViewController.swift */,
10711075
8AEB28AB265FF42500EC7892 /* CarPlayNavigationViewControllerDelegate.swift */,
1076+
8AB316A826BA026B00C3AC76 /* MapTemplateProvider.swift */,
1077+
8AB316AA26BA029100C3AC76 /* MapTemplateProviderDelegate.swift */,
10721078
358E31D522562697009B3EC2 /* CarPlayCompassView.swift */,
10731079
352C35BF2134958F00D77796 /* RecentItem.swift */,
10741080
8A1943A82685DC680066E2F8 /* NavigationGeocodedPlacemark.swift */,
@@ -2389,7 +2395,9 @@
23892395
351BEC051E5BCC6C006FE110 /* LaneView.swift in Sources */,
23902396
C5A7EC5C1FD610A80008B9BA /* VisualInstructionComponent.swift in Sources */,
23912397
CFD47D9020FD85EC00BC1E49 /* ResourceOptionsManager.swift in Sources */,
2398+
8AB316AB26BA029100C3AC76 /* MapTemplateProviderDelegate.swift in Sources */,
23922399
B44177F82649B08400781319 /* UserLocationStyle.swift in Sources */,
2400+
8AB316A926BA026B00C3AC76 /* MapTemplateProvider.swift in Sources */,
23932401
351BEC0D1E5BCC72006FE110 /* Bundle.swift in Sources */,
23942402
8DF399B21FB257B30034904C /* UIGestureRecognizer.swift in Sources */,
23952403
DA8F3A7823B5DB7900B56786 /* SpeedLimitStyleKit.swift in Sources */,

Sources/MapboxNavigation/CarPlayManager.swift

Lines changed: 67 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ public class CarPlayManager: NSObject {
7979
*/
8080
public var styles: [Style] {
8181
didSet {
82-
if let mapViewController = carPlayMapViewController {
83-
mapViewController.styles = styles
84-
}
82+
carPlayMapViewController?.styles = styles
8583
carPlayNavigationViewController?.styles = styles
8684
}
8785
}
@@ -182,7 +180,7 @@ public class CarPlayManager: NSObject {
182180
private weak var navigationService: NavigationService?
183181
private var idleTimerCancellable: IdleTimerManager.Cancellable?
184182

185-
internal var mapTemplateProvider: MapTemplateProvider
183+
var mapTemplateProvider: MapTemplateProvider
186184

187185
/**
188186
Initializes a new CarPlay manager that manages a connection to the CarPlay interface.
@@ -200,10 +198,10 @@ public class CarPlayManager: NSObject {
200198
carPlayNavigationViewControllerClass: nil)
201199
}
202200

203-
internal init(styles: [Style]? = nil,
204-
directions: Directions? = nil,
205-
eventsManager: NavigationEventsManager? = nil,
206-
carPlayNavigationViewControllerClass: CarPlayNavigationViewController.Type? = nil) {
201+
init(styles: [Style]? = nil,
202+
directions: Directions? = nil,
203+
eventsManager: NavigationEventsManager? = nil,
204+
carPlayNavigationViewControllerClass: CarPlayNavigationViewController.Type? = nil) {
207205
self.styles = styles ?? [DayStyle(), NightStyle()]
208206
let mapboxDirections = directions ?? NavigationSettings.shared.directions
209207
self.directions = mapboxDirections
@@ -331,11 +329,11 @@ extension CarPlayManager: CPApplicationDelegate {
331329
}
332330

333331
func reloadButtons(for mapTemplate: CPMapTemplate) {
334-
guard let mapViewController = carPlayMapViewController else {
332+
guard let carPlayMapViewController = carPlayMapViewController else {
335333
return
336334
}
337335

338-
let traitCollection = mapViewController.traitCollection
336+
let traitCollection = carPlayMapViewController.traitCollection
339337

340338
if let leadingButtons = delegate?.carPlayManager(self,
341339
leadingNavigationBarButtonsCompatibleWith: traitCollection,
@@ -356,7 +354,7 @@ extension CarPlayManager: CPApplicationDelegate {
356354
in: mapTemplate,
357355
for: .browsing) {
358356
mapTemplate.mapButtons = mapButtons
359-
} else if let mapButtons = self.browsingMapButtons(for: mapTemplate) {
357+
} else if let mapButtons = browsingMapButtons(for: mapTemplate) {
360358
mapTemplate.mapButtons = mapButtons
361359
}
362360
}
@@ -369,7 +367,7 @@ extension CarPlayManager: CPApplicationDelegate {
369367
in: mapTemplate,
370368
for: .browsing) {
371369
mapTemplate.mapButtons = mapButtons
372-
} else if let mapButtons = self.browsingMapButtons(for: mapTemplate) {
370+
} else if let mapButtons = browsingMapButtons(for: mapTemplate) {
373371
mapTemplate.mapButtons = mapButtons
374372
}
375373

@@ -378,16 +376,17 @@ extension CarPlayManager: CPApplicationDelegate {
378376
}
379377

380378
private func browsingMapButtons(for mapTemplate: CPMapTemplate) -> [CPMapButton]? {
381-
guard let mapViewController = carPlayMapViewController else {
379+
guard let carPlayMapViewController = carPlayMapViewController else {
382380
return nil
383381
}
384382
var mapButtons = [
385-
mapViewController.recenterButton,
386-
mapViewController.zoomInButton,
387-
mapViewController.zoomOutButton
383+
carPlayMapViewController.recenterButton,
384+
carPlayMapViewController.zoomInButton,
385+
carPlayMapViewController.zoomOutButton
388386
]
389-
let panMapButton = mapViewController.panMapButton ?? mapViewController.panningInterfaceDisplayButton(for: mapTemplate)
390-
mapViewController.panMapButton = panMapButton
387+
let panMapButton = carPlayMapViewController.panMapButton ??
388+
carPlayMapViewController.panningInterfaceDisplayButton(for: mapTemplate)
389+
carPlayMapViewController.panMapButton = panMapButton
391390
mapButtons.insert(panMapButton, at: 1)
392391

393392
return mapButtons
@@ -400,13 +399,17 @@ extension CarPlayManager: CPApplicationDelegate {
400399
extension CarPlayManager: CPInterfaceControllerDelegate {
401400

402401
public func templateWillAppear(_ template: CPTemplate, animated: Bool) {
402+
delegate?.carPlayManager(self, templateWillAppear: template, animated: animated)
403+
403404
if template == interfaceController?.rootTemplate,
404-
let mapViewController = carPlayMapViewController {
405-
mapViewController.recenterButton.isHidden = true
405+
let carPlayMapViewController = carPlayMapViewController {
406+
carPlayMapViewController.recenterButton.isHidden = true
406407
}
407408
}
408409

409410
public func templateDidAppear(_ template: CPTemplate, animated: Bool) {
411+
delegate?.carPlayManager(self, templateDidAppear: template, animated: animated)
412+
410413
guard interfaceController?.topTemplate == mainMapTemplate,
411414
template == interfaceController?.rootTemplate,
412415
let carPlayMapViewController = carPlayMapViewController else { return }
@@ -417,21 +420,35 @@ extension CarPlayManager: CPInterfaceControllerDelegate {
417420
}
418421

419422
public func templateWillDisappear(_ template: CPTemplate, animated: Bool) {
423+
delegate?.carPlayManager(self, templateWillDisappear: template, animated: animated)
424+
420425
guard let interfaceController = interfaceController,
421426
let topTemplate = interfaceController.topTemplate,
422427
type(of: topTemplate) == CPSearchTemplate.self ||
423428
interfaceController.templates.count == 1 else { return }
424429

425430
navigationMapView?.navigationCamera.follow()
426431
}
432+
433+
public func templateDidDisappear(_ template: CPTemplate, animated: Bool) {
434+
delegate?.carPlayManager(self, templateDidDisappear: template, animated: animated)
435+
}
427436
}
428437

429438
@available(iOS 12.0, *)
430439
extension CarPlayManager {
431440

441+
/**
442+
Calculates routes to the given destination using the [Mapbox Directions API](https://www.mapbox.com/api-documentation/navigation/#directions) and previews them on a map.
443+
444+
Upon successful calculation a new template will be pushed onto the template navigation hierarchy.
445+
446+
- parameter destination: A final destination `Waypoint`.
447+
- parameter completionHandler: A closure to be executed when the calculation completes.
448+
*/
432449
public func previewRoutes(to destination: Waypoint, completionHandler: @escaping CompletionHandler) {
433-
guard let rootViewController = carPlayMapViewController,
434-
let userLocation = rootViewController.navigationMapView.mapView.location.latestLocation else {
450+
guard let carPlayMapViewController = carPlayMapViewController,
451+
let userLocation = carPlayMapViewController.navigationMapView.mapView.location.latestLocation else {
435452
completionHandler()
436453
return
437454
}
@@ -451,29 +468,46 @@ extension CarPlayManager {
451468
previewRoutes(between: [origin, destination], completionHandler: completionHandler)
452469
}
453470

471+
/**
472+
Allows to preview routes for a list of `Waypoint` objects.
473+
474+
- parameter waypoints: A list of `Waypoint` objects.
475+
- parameter completionHandler: A closure to be executed when the calculation completes.
476+
*/
454477
public func previewRoutes(between waypoints: [Waypoint], completionHandler: @escaping CompletionHandler) {
455478
let options = NavigationRouteOptions(waypoints: waypoints)
456479
previewRoutes(for: options, completionHandler: completionHandler)
457480
}
458481

482+
/**
483+
Calculates routes satisfying the given options using the [Mapbox Directions API](https://www.mapbox.com/api-documentation/navigation/#directions) and previews them on a map.
484+
485+
- parameter routeOptions: A `RouteOptions` object, which specifies the criteria for results
486+
returned by the Mapbox Directions API.
487+
- parameter completionHandler: A closure to be executed when the calculation completes.
488+
*/
459489
public func previewRoutes(for options: RouteOptions, completionHandler: @escaping CompletionHandler) {
460490
calculate(options) { [weak self] (session, result) in
491+
guard let self = self else {
492+
completionHandler()
493+
return
494+
}
461495

462-
self?.didCalculate(result,
463-
in: session,
464-
for: options,
465-
completionHandler: completionHandler)
496+
self.didCalculate(result,
497+
in: session,
498+
for: options,
499+
completionHandler: completionHandler)
466500
}
467501
}
468502

469-
internal func calculate(_ options: RouteOptions, completionHandler: @escaping Directions.RouteCompletionHandler) {
503+
func calculate(_ options: RouteOptions, completionHandler: @escaping Directions.RouteCompletionHandler) {
470504
directions.calculateWithCache(options: options, completionHandler: completionHandler)
471505
}
472506

473-
internal func didCalculate(_ result: Result<RouteResponse, DirectionsError>,
474-
in session: Directions.Session,
475-
for routeOptions: RouteOptions,
476-
completionHandler: CompletionHandler) {
507+
func didCalculate(_ result: Result<RouteResponse, DirectionsError>,
508+
in session: Directions.Session,
509+
for routeOptions: RouteOptions,
510+
completionHandler: CompletionHandler) {
477511
defer {
478512
completionHandler()
479513
}
@@ -826,6 +860,8 @@ extension CarPlayManager: CarPlayMapViewControllerDelegate {
826860
}
827861
}
828862

863+
// MARK: - MapTemplateProviderDelegate methods
864+
829865
@available(iOS 12.0, *)
830866
extension CarPlayManager: MapTemplateProviderDelegate {
831867

@@ -895,50 +931,3 @@ extension CarPlayManager {
895931
idleTimerCancellable = nil
896932
}
897933
}
898-
899-
@available(iOS 12.0, *)
900-
internal protocol MapTemplateProviderDelegate: AnyObject {
901-
902-
func mapTemplateProvider(_ provider: MapTemplateProvider,
903-
mapTemplate: CPMapTemplate,
904-
leadingNavigationBarButtonsCompatibleWith traitCollection: UITraitCollection,
905-
for activity: CarPlayActivity) -> [CPBarButton]?
906-
907-
func mapTemplateProvider(_ provider: MapTemplateProvider,
908-
mapTemplate: CPMapTemplate,
909-
trailingNavigationBarButtonsCompatibleWith traitCollection: UITraitCollection,
910-
for activity: CarPlayActivity) -> [CPBarButton]?
911-
}
912-
913-
@available(iOS 12.0, *)
914-
internal class MapTemplateProvider: NSObject {
915-
916-
weak var delegate: MapTemplateProviderDelegate?
917-
918-
func mapTemplate(forPreviewing trip: CPTrip,
919-
traitCollection: UITraitCollection,
920-
mapDelegate: CPMapTemplateDelegate) -> CPMapTemplate {
921-
let mapTemplate = createMapTemplate()
922-
mapTemplate.mapDelegate = mapDelegate
923-
924-
if let leadingButtons = delegate?.mapTemplateProvider(self,
925-
mapTemplate: mapTemplate,
926-
leadingNavigationBarButtonsCompatibleWith: traitCollection,
927-
for: .previewing) {
928-
mapTemplate.leadingNavigationBarButtons = leadingButtons
929-
}
930-
931-
if let trailingButtons = delegate?.mapTemplateProvider(self,
932-
mapTemplate: mapTemplate,
933-
trailingNavigationBarButtonsCompatibleWith: traitCollection,
934-
for: .previewing) {
935-
mapTemplate.trailingNavigationBarButtons = trailingButtons
936-
}
937-
938-
return mapTemplate
939-
}
940-
941-
open func createMapTemplate() -> CPMapTemplate {
942-
return CPMapTemplate()
943-
}
944-
}

Sources/MapboxNavigation/CarPlayManagerDelegate.swift

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,34 @@ public protocol CarPlayManagerDelegate: AnyObject, UnimplementedLogging {
161161
didAdd finalDestinationAnnotation: PointAnnotation,
162162
to parentViewController: UIViewController,
163163
pointAnnotationManager: PointAnnotationManager)
164+
165+
/**
166+
Called when a template presented by the `CarPlayManager` is about to appear on the screen.
167+
*/
168+
func carPlayManager(_ carPlayManager: CarPlayManager,
169+
templateWillAppear template: CPTemplate,
170+
animated: Bool)
171+
172+
/**
173+
Called when a template presented by the `CarPlayManager` has finished appearing on the screen.
174+
*/
175+
func carPlayManager(_ carPlayManager: CarPlayManager,
176+
templateDidAppear template: CPTemplate,
177+
animated: Bool)
178+
179+
/**
180+
Called when a template presented by the `CarPlayManager` is about to disappear from the screen.
181+
*/
182+
func carPlayManager(_ carPlayManager: CarPlayManager,
183+
templateWillDisappear template: CPTemplate,
184+
animated: Bool)
185+
186+
/**
187+
Called when a template presented by the `CarPlayManager` has finished disappearing from the screen.
188+
*/
189+
func carPlayManager(_ carPlayManager: CarPlayManager,
190+
templateDidDisappear template: CPTemplate,
191+
animated: Bool)
164192
}
165193

166194
@available(iOS 12.0, *)
@@ -273,4 +301,40 @@ public extension CarPlayManagerDelegate {
273301
pointAnnotationManager: PointAnnotationManager) {
274302
logUnimplemented(protocolType: CarPlayManagerDelegate.self, level: .debug)
275303
}
304+
305+
/**
306+
`UnimplementedLogging` prints a warning to standard output the first time this method is called.
307+
*/
308+
func carPlayManager(_ carPlayManager: CarPlayManager,
309+
templateWillAppear template: CPTemplate,
310+
animated: Bool) {
311+
logUnimplemented(protocolType: CarPlayManagerDelegate.self, level: .debug)
312+
}
313+
314+
/**
315+
`UnimplementedLogging` prints a warning to standard output the first time this method is called.
316+
*/
317+
func carPlayManager(_ carPlayManager: CarPlayManager,
318+
templateDidAppear template: CPTemplate,
319+
animated: Bool) {
320+
logUnimplemented(protocolType: CarPlayManagerDelegate.self, level: .debug)
321+
}
322+
323+
/**
324+
`UnimplementedLogging` prints a warning to standard output the first time this method is called.
325+
*/
326+
func carPlayManager(_ carPlayManager: CarPlayManager,
327+
templateWillDisappear template: CPTemplate,
328+
animated: Bool) {
329+
logUnimplemented(protocolType: CarPlayManagerDelegate.self, level: .debug)
330+
}
331+
332+
/**
333+
`UnimplementedLogging` prints a warning to standard output the first time this method is called.
334+
*/
335+
func carPlayManager(_ carPlayManager: CarPlayManager,
336+
templateDidDisappear template: CPTemplate,
337+
animated: Bool) {
338+
logUnimplemented(protocolType: CarPlayManagerDelegate.self, level: .debug)
339+
}
276340
}

0 commit comments

Comments
 (0)