Skip to content

Fix RCTAppearance setColorScheme crashing CarPlay apps (non-UIWindowScene guard) - #57876

Open
SnowingFox wants to merge 2 commits into
react:mainfrom
SnowingFox:fix/issue-57863-rctappearance-carplay-scene-guard
Open

Fix RCTAppearance setColorScheme crashing CarPlay apps (non-UIWindowScene guard)#57876
SnowingFox wants to merge 2 commits into
react:mainfrom
SnowingFox:fix/issue-57863-rctappearance-carplay-scene-guard

Conversation

@SnowingFox

Copy link
Copy Markdown

Summary:

Fixes #57863

RCTAppearance setColorScheme: (also reached via Appearance.setColorScheme() and setUserInterfaceStyle) iterates RCTSharedApplication().connectedScenes and reads scene.windows on every scene. connectedScenes contains UIScene objects of any class, and a CarPlay CPTemplateApplicationScene is a UIScene that does not implement windows, so the message send raises -[CPTemplateApplicationScene windows]: unrecognized selector and the app aborts.

Fix: guard each scene with isKindOfClass:[UIWindowScene class] and skip non-UIWindowScene objects before touching .windows, mirroring the existing pattern already used in RCTUtils.mm (if (![scene isKindOfClass:[UIWindowScene class]]) { continue; }).

Note: RCTDevMenu.mm showOnShake has the same unguarded for (UIWindowScene *scene ...) loop and would crash identically in a CarPlay context; left untouched here to keep this fix minimal, but it should get the same guard.

Changelog:

[IOS] [FIXED] - RCTAppearance.setColorScheme() no longer crashes CarPlay apps when connectedScenes contains a non-UIWindowScene

Test Plan:

No jest path exists for this code: it is Objective-C, iOS-only, and iOS cannot be built in the Linux environment this PR was developed in. Correctness is by code inspection.

Commands run (in the branch worktree):

  • git diff packages/react-native/React/CoreModules/RCTAppearance.mm — confirms the only change is the 3-line guard:
  for (UIWindowScene *scene in RCTSharedApplication().connectedScenes) {
+   if (![scene isKindOfClass:[UIWindowScene class]]) {
+     continue;
+   }
    [windows addObjectsFromArray:scene.windows];
  }
  • Code inspection of the edited region in full:
- (void)setColorScheme:(NSString *)style
{
  UIUserInterfaceStyle userInterfaceStyle = [RCTConvert UIUserInterfaceStyle:style];
  NSMutableArray<UIWindow *> *windows = [NSMutableArray new];
  for (UIWindowScene *scene in RCTSharedApplication().connectedScenes) {
    if (![scene isKindOfClass:[UIWindowScene class]]) {
      continue;
    }
    [windows addObjectsFromArray:scene.windows];
  }

  for (UIWindow *window in windows) {
    window.overrideUserInterfaceStyle = userInterfaceStyle;
  }
}

The guard makes setColorScheme tolerate any non-UIWindowScene object in connectedScenes by skipping it before the .windows message send. isKindOfClass: is safe to send to any UIScene (all are NSObject-derived), so the previously-crashing path is unreachable for CarPlay scenes.

This matches the reporter's production patch-package fix that has been field-tested on-device since 2026-08-02.

Summary:
`RCTAppearance setColorScheme:` iterates `RCTSharedApplication().connectedScenes`
and reads `scene.windows` on every scene, but `connectedScenes` can contain
`UIScene` objects of any class. A CarPlay `CPTemplateApplicationScene` is a
`UIScene` without a `windows` property, so the message send raises
`-[CPTemplateApplicationScene windows]: unrecognized selector` and the app aborts
whenever `Appearance.setColorScheme()` / `setUserInterfaceStyle()` is called.

Guard each scene with `isKindOfClass:[UIWindowScene class]` before touching
`.windows`, mirroring the existing pattern in `RCTUtils.mm`. Fixes react#57863.

Changelog:
[IOS] [FIXED] - RCTAppearance.setColorScheme() no longer crashes CarPlay apps with a non-UIWindowScene in connectedScenes

Test Plan:
No jest path (Objective-C, iOS-only; iOS cannot be built in this Linux environment).
The added guard makes setColorScheme tolerate any non-UIWindowScene object by
skipping it before the `.windows` message send. Verified by code inspection and it
matches the reporter's production patch-package field-tested since 2026-08-02.
@meta-cla

meta-cla Bot commented Aug 10, 2026

Copy link
Copy Markdown

Hi @SnowingFox!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla

meta-cla Bot commented Aug 10, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 10, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Aug 10, 2026
UIUserInterfaceStyle userInterfaceStyle = [RCTConvert UIUserInterfaceStyle:style];
NSMutableArray<UIWindow *> *windows = [NSMutableArray new];
for (UIWindowScene *scene in RCTSharedApplication().connectedScenes) {
if (![scene isKindOfClass:[UIWindowScene class]]) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is kind of class is kind of expensive. Can we replace this with respondToSelector:@selector(windows)?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in f6bdb53 — replaced isKindOfClass:[UIWindowScene class] with respondsToSelector:@selector(windows). Both are safe on any UIScene (all NSObject-derived); the selector check avoids the class-hierarchy walk. Thanks!

…isKindOfClass

isKindOfClass walks the class hierarchy; respondsToSelector is a single
lookup. Both are safe to send to any UIScene (all NSObject-derived).
@meta-codesync

meta-codesync Bot commented Aug 10, 2026

Copy link
Copy Markdown

@christophpurrer has imported this pull request. If you are a Meta employee, you can view this in D115451211.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Appearance.setColorScheme() crashes any CarPlay app: RCTAppearance sends windows to every connected scene

2 participants