mapbox / mapbox/mapbox-maps-ios

MapView never renders in CarPlay dashboard/instrument-cluster scenes — parentScene resolves nil for non-CPWindow CarPlay windows

Open
#2,430 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

auto-triaged bug :beetle:
Dominant language
Swift
Stars
601
Forks
196
PR merge metrics
No merged PRs in 30d

Description

**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:

```swift
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:

```swift
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:

```swift
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**
1. CarPlay nav app with a dashboard scene declared (`CPSupportsDashboardNavigationScene`).
2. In the dashboard scene delegate, add any `MapView` to the provided window's root view controller.
3. Attach a dashboard-capable head unit (the simulator cannot display the dashboard scene; a real car or the standalone CarPlay Simulator app is required).
4. Result: UIKit siblings render; the map never paints. Breakpoint in `updateFromDisplayLink` confirms `window?.parentScene == nil` → immediate pause.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in Sources/MapboxMaps/Foundation/Extensions/UIWindow+ParentScene.swift and inspect the existing UIScene.allWindows helper, then trace its use from Sources/MapboxMaps/Foundation/MapView.swift in updateFromDisplayLink. Reproduce with a real dashboard or instrument-cluster CarPlay scene and verify that MapView renders there while the head-unit scene remains unaffected.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, swift
Domain
mobile
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.