fix(mobile): adopt the UIKit scene lifecycle so iOS 27 can launch #151
No reviewers
Labels
No labels
dependencies
major
security-pin
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
trails-cool/trails!151
Loading…
Reference in a new issue
No description provided.
Delete branch "ios-27-scene-lifecycle"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
On Xcode 27, the app cannot be run on an iOS 27 simulator or device at all — it is killed before any JS executes:
Apple made scene adoption mandatory for anything linked against the iOS 27 SDK (TN3187). Expo's prebuild template still emits an AppDelegate/window lifecycle with no
UIApplicationSceneManifest, so a freshly prebuilt app has no scene support.This is not caused by any change of ours and is not SDK-specific — SDK 56 (this branch) and SDK 57 fail identically. Expo tracks it in expo/expo#46664 (accepted, unreleased) and #46663; the fix depends on React Native 0.87+, so it lands no earlier than SDK 58.
The fix
A config plugin (
apps/mobile/plugins/with-ios-scene-lifecycle) that injectsUIApplicationSceneManifestintoInfo.plistand patches the generatedAppDelegate.swiftwith aSceneDelegate.Taken from narrowstacks/dorkroom#205, itself derived from YesterdaysLemon/expo-ios-scene-lifecycle-plugin. It does more than the minimum manifest, which matters for us:
trailscool://auth/callback, which would otherwise breakUIApplicationDelegatelife-cycle methods that Expo modules still rely onconnectionOptionsEvery anchor in the AppDelegate patch throws when it stops matching, so a future Expo template change fails
prebuildloudly instead of silently producing a non-scene, crashing app.Two adjustments this repo needed
@expo/config-pluginsas a direct devDependency (~56.0.16)apps/mobile/plugins/**Verification
expo prebuild --clean --platform iosinjects the manifest andSceneDelegate;pnpm typecheck14/14,lint14/14,test12/12.Notes
Remove this plugin once Expo ships a scene-based template — the header comment says so and names the issues to re-check on each SDK upgrade.
The same commit is also on #150 (Expo SDK 57). Whichever lands first, the other should drop it — it is deliberately independent of the SDK bump.
🤖 Generated with Claude Code
Apps linked against the iOS 27 SDK are killed at launch unless they adopt UIScene (Apple TN3187). Expo's prebuild template still emits an AppDelegate/window lifecycle with no UIApplicationSceneManifest, so a freshly prebuilt app dies before any JS runs: Application failed to launch: UIScene life cycle is required for apps built with this SDK. Anyone on Xcode 27 currently cannot run the app on an iOS 27 simulator or device at all. Expo tracks this in expo/expo#46664 (accepted, unreleased); the fix is tied to React Native 0.87+, so it lands no earlier than SDK 58. Adds a config plugin that injects UIApplicationSceneManifest into Info.plist and patches the generated AppDelegate.swift with a SceneDelegate. Taken from narrowstacks/dorkroom#205, itself derived from YesterdaysLemon/expo-ios-scene-lifecycle-plugin. Beyond the minimum manifest it forwards deep links, universal links and quick actions to the Expo app-delegate subscribers, and re-dispatches the scene activation callbacks, because UIKit stops calling the UIApplicationDelegate life-cycle methods that Expo modules still rely on. Deep-link forwarding matters here specifically: OAuth sign-in returns through trailscool://auth/callback. Two adjustments were needed for this repo: - @expo/config-plugins becomes a direct devDependency. pnpm's isolated linker does not hoist it, so a local plugin cannot resolve it (the upstream PR uses bun, where it happens to be hoisted). - eslint gets an override for apps/mobile/plugins. Config plugins run in Node during prebuild and must be CommonJS, which the repo's ESM rules otherwise reject. Every anchor in the AppDelegate patch throws when it stops matching, so a future template change fails prebuild loudly rather than silently producing a non-scene, crashing app. Remove the plugin once Expo ships a scene-based template. Verified against SDK 56 on this branch: prebuild injects the manifest and the SceneDelegate. The same plugin was verified end to end on an iOS 27 simulator (iPhone 17 Pro, Xcode 27), where the app builds, launches and loads its bundle from Metro — without it the identical build is killed at launch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>