Environment
- MapboxMaps 11.18.3 (also present in current
main)
- iOS 18.x, CarPlay navigation app (
com.apple.developer.carplay-maps), real head unit
Summary
A MapView placed in the CarPlay dashboard scene (CPTemplateApplicationDashboardScene, iOS ≥ 13.4) or instrument-cluster scene never draws a single frame — the Metal view stays transparent/black while sibling UIKit views in the same window render normally. The head-unit (CPTemplateApplicationScene) map is unaffected.
Root cause (traced in SDK source)
MapView only runs its display link while shouldRunDisplayLink(for: window?.parentScene) is true, and updateFromDisplayLink re-pauses on every frame when it is false (Sources/MapboxMaps/Foundation/MapView.swift).
UIWindow.parentScene (Sources/MapboxMaps/Foundation/Extensions/UIWindow+ParentScene.swift) resolves:
switch self {
case let carPlayWindow as CPWindow:
return carPlayWindow.templateApplicationScene // head unit — works
default:
return windowScene // typed UIWindowScene?
}
The dashboard window handed to CPTemplateApplicationDashboardSceneDelegate.templateApplicationDashboardScene(_:didConnect:to:) is a plain UIWindow (not a CPWindow) attached to a scene that is not a UIWindowScene, so windowScene is nil → parentScene is nil → shouldRunDisplayLink(nil) returns false → the display link never starts, and the scene-activation notification path can't rescue it because the per-frame check re-pauses immediately.
Notably, the UIScene.allWindows helper in the same file already knows about both scene types:
if let carPlayDashboardScene = self as? CPTemplateApplicationDashboardScene {
return [carPlayDashboardScene.dashboardWindow]
}
— only parentScene misses the reverse mapping.
Suggested fix
In the default: branch, fall back to scanning connected scenes with the existing helper when windowScene is nil:
default:
if let scene = windowScene { return scene }
return UIApplication.shared.connectedScenes.first { $0.allWindows.contains(self) }
We are running exactly this as a local pod patch and the dashboard map renders correctly with it. (If per-frame cost is a concern, the result could be cached per window — the per-frame updateFromDisplayLink check calls parentScene on every tick.)
Repro sketch
- CarPlay nav app with a dashboard scene declared (
CPSupportsDashboardNavigationScene).
- In the dashboard scene delegate, add any
MapView to the provided window's root view controller.
- Attach a dashboard-capable head unit (the simulator cannot display the dashboard scene; a real car or the standalone CarPlay Simulator app is required).
- Result: UIKit siblings render; the map never paints. Breakpoint in
updateFromDisplayLink confirms window?.parentScene == nil → immediate pause.
Environment
main)com.apple.developer.carplay-maps), real head unitSummary
A
MapViewplaced in the CarPlay dashboard scene (CPTemplateApplicationDashboardScene, iOS ≥ 13.4) or instrument-cluster scene never draws a single frame — the Metal view stays transparent/black while sibling UIKit views in the same window render normally. The head-unit (CPTemplateApplicationScene) map is unaffected.Root cause (traced in SDK source)
MapViewonly runs its display link whileshouldRunDisplayLink(for: window?.parentScene)is true, andupdateFromDisplayLinkre-pauses on every frame when it is false (Sources/MapboxMaps/Foundation/MapView.swift).UIWindow.parentScene(Sources/MapboxMaps/Foundation/Extensions/UIWindow+ParentScene.swift) resolves:The dashboard window handed to
CPTemplateApplicationDashboardSceneDelegate.templateApplicationDashboardScene(_:didConnect:to:)is a plainUIWindow(not aCPWindow) attached to a scene that is not aUIWindowScene, sowindowSceneis nil →parentSceneis nil →shouldRunDisplayLink(nil)returns false → the display link never starts, and the scene-activation notification path can't rescue it because the per-frame check re-pauses immediately.Notably, the
UIScene.allWindowshelper in the same file already knows about both scene types:— only
parentScenemisses the reverse mapping.Suggested fix
In the
default:branch, fall back to scanning connected scenes with the existing helper whenwindowSceneis nil:We are running exactly this as a local pod patch and the dashboard map renders correctly with it. (If per-frame cost is a concern, the result could be cached per window — the per-frame
updateFromDisplayLinkcheck callsparentSceneon every tick.)Repro sketch
CPSupportsDashboardNavigationScene).MapViewto the provided window's root view controller.updateFromDisplayLinkconfirmswindow?.parentScene == nil→ immediate pause.