CarPlay: CPListItem.image degrades to placeholder glyph mid-session, only iPhone reboot recovers — FB22828125

Posting here in case other CarPlay developers are hitting the same thing, and to give Apple engineers a forum-side reference for the radar.

Filed as FB22828125.

Symptom

In a CarPlay app using CPListTemplate, UIImage instances assigned to CPListItem.image start rendering as the system placeholder glyph after extended CarPlay use (several hours to a few days of cumulative session time). Text labels and accessory chevrons still render correctly — only the leading image is affected, and it affects every visible template surface at once.

Known recovery

Once the failure starts, it survives:

  • Killing and relaunching the app
  • Force-quitting and relaunching from CarPlay itself
  • Disconnecting and reconnecting CarPlay

The only known recovery is rebooting the iPhone. After reboot, the same code path renders correctly again — until the failure reoccurs.

App-side ruling-out

  • UIImage instances passed to CPListItem.image are non-nil at failure time (verified by assertions)
  • Each template rebuild calls UIGraphicsImageRenderer afresh from UIImage(systemName:) — no caching of UIImage across rebuilds
  • Images are baked via withTintColor(_:renderingMode: .alwaysOriginal) then rasterized, so CarPlay receives a finished bitmap rather than a template image relying on its tinting pipeline
  • Same code path renders correctly on launch and for hours afterward — the input bytes are identical before and after the failure boundary

Because the failure survives both the app process and the CPTemplateApplicationScene teardown, the corrupted state appears to live in an iOS system process rather than in the app or the CarPlay session.

Question for the forum

Is there a known workaround on the app side — a different image-supply API, or a way to force the CarPlay rendering pipeline to invalidate its cache without an iPhone reboot?

Thanks for the FB number, looks like was submitted today?

You can see the status of your feedback in Feedback Assistant. There, you can track if the report is still being investigated, has a potential identifiable fix, or has been resolved in another way. The status appears beside the label "Resolution." We're unable to share any updates on specific reports on the forums.

For more details on when you'll see updates to your report, please see What to expect after submission.

Every time you generate a brand new bitmap via UIGraphicsImageRenderer and pass it to a CPListItem, the system treats it as a unique asset and sends a new bitmap. Over several hours of template rebuilds, the remote CarPlay process I would implement an app-side cache a simple dictionary for your images. If you need a specific icon with a specific tint, generate it once, cache it, and pass that exact same UIImage pointer to the CPListItem on subsequent rebuilds. The system is much better at optimizing identical object.

You mentioned you are baking the tint color into a bitmap using UIGraphicsImageRenderer Instead of rasterizing, apply the color. When you pass a symbol-configured UIImage to CarPlay, the XPC payload is tiny. It just sends the string name of the symbol and the color parameters, and the system daemon renders it natively on the CarPlay side.

Moving away from continuous bitmap generation and relying on cached images or native SymbolConfiguration payloads is in my opinion the best way to do this.

Albert
  Worldwide Developer Relations.

Thank you, yes that FB was submitted earlier today.

Two new pieces of data from a tester conversation today that I wanted to put on the record here, because they suggest the asset-accumulation theory may not be the whole story.

1. Cliff transition, not gradual degradation. I just spoke with one customer and he described the failure as "one second the screen was fine, the next it was gray boxes." Not a slow boil where one icon becomes the placeholder, then a few more, then most. Sudden onset, every visual at once.

2. Both CPListItem icons and CPListImageRowItemRowElement images fail. I have several list-row icons (connection status, adapter status) and the row-element images on my Driving and Charging tabs (which are CPListTemplates built with CPListImageRowItem rows).

  • The CPListItem rasterized SF-symbol icons are quasi-static. They're gated behind state-change snapshots and only re-rasterized on actual state transitions (connectionDisplay returning a different (symbol, tint) pair, or the adapter-action row flipping between connect/disconnect). Over a multi-hour drive the set of distinct visuals shipped from those sites is small — roughly 10 unique (symbol, tint) pairs total, repeated as the user moves through states.
  • The CPListImageRowItemRowElement images on the Driving and Charging tabs are high-churn by orders of magnitude. For example, the RPM gauges may produce hundreds of distinct bitmaps over a single drive — and there are several other continuously-varying gauges and sparklines feeding new bitmaps to other row elements several times per second.

Both surfaces are CPListTemplate image surfaces and presumably share the same Apple-side rendering code path. If the theory were "table fills up," I might imagine that the high-cardinality surface might degrade first, long before the quasi-static surface with ~10 distinct visuals could possibly contribute. Instead both surfaces appear to fail simultaneously.

That symptom shape — sudden onset, everything at once, survives app relaunch and CarPlay disconnect, only iPhone reboot recovers — reads more like a process-level fault on the iOS side (a crash, an XPC channel break, a watchdog trigger in carplayd or the render server) than a soft-limit being reached.

I'm working with affected testers/customers -- hoping one of them can capture a sysdiagnose.

CarPlay: CPListItem.image degrades to placeholder glyph mid-session, only iPhone reboot recovers — FB22828125
 
 
Q