文章称,使用 iOS 27 SDK 构建的应用必须采用 UIScene 生命周期,否则启动失败;触发条件是构建 SDK,而非手机系统版本。作者抽查的 628 个 React Native 和 Expo 项目中,583 个尚未迁移,并指出 React Native 0.88 模板已采用新生命周期。
9 月 9 日,Apple 宣布:从 2027 年 4 月起,上传到 App Store Connect 的 app 必须使用 iOS 27 SDK 构建,也就意味着必须使用 Xcode 27。使用这个 SDK 构建时,如果 app 尚未采用 UIKit scene 生命周期,就无法启动。它会在启动时停止,并报错:
Application failed to launch: UIScene life cycle is required for apps built with this SDK.
Apple 在 TN3187 中公布了这项规定。这项检查取决于构建时使用的 SDK,而不是手机上的 iOS 版本。同一个 app 如果用 Xcode 26 构建,仍然可以在 iOS 27 上运行,因此你现在的用户不会受到影响。问题会在你切换到 Xcode 27 的那一天出现。
我对数百个开源 React Native 和 Expo app 做了健康检查,这也是我用来测试 NativeKeel 的那批 app。截至 2026 年 10 月 11 日:
这个数字并不是在评价这些 app 的质量。直到几周前,React Native 和 Expo 的模板都完全没有使用 scene。
React Native 0.88 是首个在模板中采用 scene 生命周期的版本。SceneDelegate.swift 在 window scene 中启动 React Native,Info.plist 则通过 UIApplicationSceneManifest 指定这个 scene delegate。0.88 目前仍是候选发布版本,10 月 7 日发布的是 rc.4。0.87 及更早版本的模板中没有相关配置,因此迁移路径是升级版本,再从 Upgrade Helper 复制这两个文件。
Expo SDK 57 可以选择启用这项支持,需要 expo 57.0.23+ 和 expo-build-properties 57.0.20+:
["expo-build-properties", { "ios": { "enableSceneSupport": true } }]
然后重新运行 npx expo prebuild。
Expo SDK 58 自 9 月 15 日起进入 beta,默认就会生成 scene delegate。
SDK 56 及更早版本需要先升级 SDK。
怎样判断你是否已经采用了 scene 生命周期?你的 Info.plist 中应当有包含 scene 配置的 UIApplicationSceneManifest,或者 app delegate 实现了 application(_:configurationForConnecting:options:)。如果 manifest 只设置了 UIApplicationSupportsMultipleScenes,并不算完成适配。
在 0.88 的模板中,UIWindow 属于 scene delegate。AppDelegate 已经完全没有 window 属性。
许多 iOS 库仍然通过下面这种方式,查找用于展示界面的 root view controller:
UIViewController *root = [UIApplication sharedApplication].delegate.window.rootViewController;
在新模板中,这行代码会抛出错误:
-[AppDelegate window]: unrecognized selector sent to instance
我搜索了常用 React Native 库的 iOS 源码,查找没有经过 respondsToSelector: 检查就执行上述调用的代码,在 15 个仍有人使用的库中发现了它。随后,我创建了一个全新的 React Native 0.88.0-rc.4 app,并确认其中两个库会导致崩溃:react-native-blob-util 和 react-native-google-mobile-ads。只改一处,两者就都不再崩溃:
UIViewController *root = RCTPresentedViewController(); // or RCTKeyWindow().rootViewController
这两项修复都已经提交了 pull request,分别是 react-native-blob-util#498 和 react-native-google-mobile-ads#911。对于会在启动时执行这项调用的 @react-native-firebase/messaging,上游也已经有人提出修复,编号为 react-native-firebase#9359。
628 个 app 中,有 68 个至少依赖了这些库中的一个。最常见的是:
在包含修复的版本发布之前,可以用 patch-package 打补丁,将相关代码替换为上面的那一行。
采用 scene 后,UIKit 会把打开的 URL 和 universal link 交给 scene delegate。AppDelegate 中的 application(:open:options:) 和 application(:continue:restorationHandler:) 不再被调用。如果你的 scene delegate 没有把它们转发给 RCTLinkingManager,app 并不会崩溃,只是 Linking 再也不会触发。
我在一个已经迁移到 scene 的钱包 app 中发现了这个问题:无论 app 正在运行,还是通过链接启动,zcash: 支付链接都无法再传到 JavaScript。原因是 launchOptions 为 nil,URL 只会出现在 scene 的 connectionOptions 中,相关问题编号为 zingo-mobile#1595。如果你的 app 需要处理 deep link,迁移后一定要测试两种情况:app 正在运行,以及 app 已经关闭。
检查你是否已经采用 scene,方法就是上面提到的 Info.plist 检查。
Expo:使用 SDK 57 并启用 enableSceneSupport,或者使用 SDK 58。Bare React Native:规划升级到 0.88。
对照上面提到的库,检查你的依赖,在使用 Xcode 27 构建之前更新它们或打补丁。
将 URL 和 user activity 从 scene delegate 转发给 RCTLinkingManager。
在 4 月到来之前,尽早使用 Xcode 27 构建。测试 app 启动、所有会展示 picker、菜单或广告的页面,以及冷启动时的 deep link。
npx nativekeel
它会报告 app 是否已经采用 scene 生命周期、已安装的哪些库会从 app delegate 读取 window,以及 URL handler 是否仍然只存在于 AppDelegate 中。它在本地运行,不需要账号,也不会上传你的代码。如果你已经遇到了这个崩溃:
npx nativekeel explain "-[AppDelegate window]: unrecognized selector"
如果你使用 AI Agent 来完成升级,同样的检查也可以通过 MCP 使用。此外,还有一个 Claude Code plugin,安装命令是 claude plugin marketplace add AlicanAkyol/nativekeel,这样 Agent 就能在开始修改版本之前先完成检查。包含来源的更完整参考资料位于 nativekeel.com/fix/uiscene-life-cycle-required-xcode-27。
如果你维护着上面提到的某个库,希望有人协助修复,我很乐意提交 PR。
如需采取进一步措施,你可以考虑屏蔽此人,或举报滥用行为。