Skip to content

fix(messaging, ios): guard AppDelegate window access for UIScene apps - #9359

Closed
huytdps13400 wants to merge 1 commit into
invertase:mainfrom
huytdps13400:fix/messaging-ios-scene-window
Closed

huytdps13400 wants to merge 1 commit into
invertase:mainfrom
huytdps13400:fix/messaging-ios-scene-window

Conversation

@huytdps13400

Copy link
Copy Markdown

Description

RNFBMessaging+NSNotificationCenter.m reads [UIApplication sharedApplication].delegate.window in application_onDidFinishLaunchingNotification: and application_onDidEnterForeground. window is an optional property on UIApplicationDelegate. Apps that use the UIScene life cycle often remove it from their AppDelegate, because the window belongs to the scene delegate. For those apps the read throws -[AppDelegate window]: unrecognized selector sent to instance at launch.

This PR adds a respondsToSelector:@selector(window) check before the window reads in both places. If the delegate has no window, the code skips the RCTRootView isHeadless appProperties update, which already happens when window is nil. The isHeadless flag on the module is still set. Apps whose AppDelegate keeps window, like the e2e app and test-rn-bare, behave the same as before.

Related issues

Fixes #8796

Release Summary

fix(messaging, ios): no longer crash at launch in UIScene apps whose AppDelegate has no window property

Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
    • Yes
  • My change supports the following platforms;
    • Android
    • iOS
    • Other (macOS, web)
  • My change includes tests;
    • e2e tests added or updated in packages/\*\*/e2e
    • jest tests added or updated in packages/\*\*/__tests__
  • I have updated TypeScript types that are affected by my change.
  • This is a breaking change;
    • Yes
    • No

Test Plan

The repo has no native unit-test target for this file, and the e2e app keeps AppDelegate.window on purpose, so e2e can't hit this path. I tested it with a small out-of-tree harness instead. The harness compiles the real RNFBMessaging+NSNotificationCenter.m for Mac Catalyst against UIKit, with stub headers for React, RNFBApp and Firebase. It swaps +[UIApplication sharedApplication] for a fake app and calls both notification handlers directly:

  1. Scene-style AppDelegate with no window property, background launch from a remote notification, then foreground.
  2. Legacy AppDelegate whose window.rootViewController.view is an RCTRootView with isHeadless: NO. This checks that appProperties still change to YES on a headless launch and back to NO on foreground.

Before (main @ c147145):

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SceneAppDelegate window]: unrecognized selector sent to instance 0x103386ac0'

After:

PASS: scene delegate without window
PASS: legacy delegate with window/RCTRootView

clang-format --style=Google -n -Werror (the lint:ios:check config, clang-format 1.7.0) passes on the messaging iOS sources.

This fix was prepared with AI assistance (Claude Code) and verified locally with the tests above.

🔥

🤖 Generated with Claude Code

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

`window` is an optional UIApplicationDelegate property. Apps on the
UIScene life cycle often drop it from their AppDelegate, so reading
`delegate.window` raised an unrecognized-selector exception at launch
and when entering the foreground. Check respondsToSelector first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mikehardy
mikehardy force-pushed the fix/messaging-ios-scene-window branch from c9b5a38 to b86b5f2 Compare October 16, 2026 11:15

@mikehardy mikehardy left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hey @huytdps13400 👋

Thanks for this — clean, minimal fix for a real crash on scene-only AppDelegates (the ones that actually omit window, which our fixtures intentionally keep around for other probes). I scanned the rest of the library for the same delegate.window pattern and this looks like the only spot.

I rebased onto current main so it is ready to land. Planning to cut a release with this shortly.

Cheers

@mikehardy

Copy link
Copy Markdown
Collaborator

Hey @huytdps13400 👋

Thanks again for the fix — the approach was exactly right. We could not merge this PR because the CLA was not signed, so I re-implemented the same guard on a fresh branch and opened a replacement:

#9375

Going to close this one as obsolete in favor of that. Really appreciate you digging into the UIScene crash path.

Cheers

@mikehardy

Copy link
Copy Markdown
Collaborator

Obsolete in favor of #9375 (CLA). Same fix, maintainer re-implementation.

@mikehardy mikehardy closed this Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🐛] Messaging module crashes on startup in scene-based life-cycle apps

3 participants