If your iOS app still creates its window in AppDelegate, it will not start when you build it with Xcode 27. No fallback, no partial UI: UIKit stops the process at launch. Apple has been flagging this for two years, and in the last two weeks React Native and Expo shipped their answers, joining Flutter and Capacitor. This guide explains what changed, how to check whether your app is affected, and a migration order that works for native, Flutter, React Native, Expo, Capacitor and Unity projects.
What Apple changed, and when it bites
Apple's documentation is now direct: "Beginning in iOS 27, iPadOS 27, Mac Catalyst 27, tvOS 27, and visionOS 27, apps built with the latest SDK must adopt the scene-based life cycle or they fail to launch" (Apple, Transitioning to the UIKit scene-based life cycle). The warning has been in the console for a while. Since iOS 18.4, UIKit logged "This process does not adopt UIScene lifecycle", and iOS 26 changed it to "UIScene lifecycle will soon be required".
A build made with Xcode 27 that has not migrated fails with a message like this, reported by both the Flutter and Expo teams during the beta:
Application failed to launch: UIScene life cycle is required for apps built
with this SDK. See Technote TN3187 for more information on migration.
Two points decide how urgent this is for you:
- The trigger is the SDK, not the device. Apps already on the App Store keep running on iOS 27, and builds made with Xcode 26 still launch. The Ionic team put it plainly in the Capacitor 8.5 announcement: until you adopt scenes, "Xcode 27 is closed to you".
- Xcode 26 has an end date. On 9 September 2026 Apple opened submissions for the new OS releases and announced that, starting April 2027, iOS and iPadOS apps uploaded to App Store Connect must be built with the iOS 27 SDK or later (Apple Developer News). After that month, every update, including an urgent bug fix, has to come from Xcode 27, which means the migration has to be done first.
So the real deadline is not April. It is the first day you need an Xcode 27 feature, or the first urgent fix after April, whichever comes first.
Is your app affected?
Apple gives two conditions. Your app needs to migrate if either is true:
- The
UIApplicationSceneManifestkey is missing fromInfo.plist, or it has no configurations. - Your app delegate does not implement
application(_:configurationForConnecting:options:).
Quick checks you can run today:
- Open
Info.plistand search forUIApplicationSceneManifest. - Run the current build on an iOS 26 simulator and look for the "UIScene lifecycle will soon be required" line in the console.
- Search your native code for
window =insidedidFinishLaunchingWithOptions, and forUIApplication.shared.keyWindow,UIApplication.shared.windowsandUIScreen.main. These are the places that assume one app, one window.
Projects created from Xcode templates since iOS 13 usually already have a scene delegate. The apps at risk are older native apps, and almost every cross-platform app, because framework templates kept the AppDelegate-only setup for years.
What actually moves from AppDelegate to SceneDelegate
The scene model splits your app into two life cycles. The process still starts once and UIApplicationDelegate still handles process-level work: push token registration, SDK initialisation, background tasks. Everything tied to visible UI moves to a UIWindowSceneDelegate: creating the window, the root view controller, foreground and background transitions, URL opens and user activities.
Apple's migration guide and TN3187 map the callbacks like this:
| AppDelegate (old) | SceneDelegate (new) |
|---|---|
applicationDidBecomeActive(_:) | sceneDidBecomeActive(_:) |
applicationWillResignActive(_:) | sceneWillResignActive(_:) |
applicationDidEnterBackground(_:) | sceneDidEnterBackground(_:) |
applicationWillEnterForeground(_:) | sceneWillEnterForeground(_:) |
Window created in didFinishLaunchingWithOptions | Window created in scene(_:willConnectTo:options:) |
application(_:open:options:) | scene(_:openURLContexts:) |
application(_:continue:restorationHandler:) | scene(_:continue:) |
The detail that causes most bugs: once you adopt scenes, UIKit stops calling the old UIApplicationDelegate UI callbacks, even if you leave them in place. Code there will not crash; it will silently stop running. If you need app-wide state, such as "is any part of the app in the foreground", Apple recommends the UIApplication notifications (for example willEnterForegroundNotification) rather than a single scene callback.
You do not have to support multiple windows. Set UIApplicationSupportsMultipleScenes to false and you get one scene, which is all the requirement asks for.
Framework by framework: where things stand
Most of our client work is cross-platform, so this is the part that decides the effort. Versions and dates below come from each project's own release notes.
| Stack | Scene support | Default for new projects | What an existing app does |
|---|---|---|---|
| Native UIKit | iOS 13+ | Xcode templates | Add scene manifest and SceneDelegate, move UI callbacks |
| Flutter | 3.38 stable; default from 3.41 | Yes, auto-migrates unmodified AppDelegate | Manual steps if AppDelegate is customised |
| React Native | 0.88 (19 Oct 2026) | Community template updated | Move entry point to SceneDelegate, forward links |
| Expo | SDK 58 (16 Oct 2026) | Yes | SDK 57: opt-in flag; SDK 58: read guide if AppDelegate is customised |
| Capacitor | 8.5 (31 Jul 2026) | Yes | npx cap migrate |
Flutter
According to the Flutter UIScene migration guide, support landed in 3.38 and became the default in 3.41. If your AppDelegate is untouched, flutter run or flutter build ios migrates the project and prints "Finished migration to UIScene lifecycle". If you customised it, which most production apps did to register method channels or native SDKs, you conform AppDelegate to FlutterImplicitEngineDelegate and move plugin registration and channel setup into didInitializeImplicitFlutterEngine. The guide warns that reading FlutterViewController from window?.rootViewController in didFinishLaunchingWithOptions can now crash. Plugin authors have their own section: plugins that listen to app lifecycle events need scene equivalents, so check every plugin you depend on for a release that mentions UIScene.
React Native
React Native 0.88, released on 19 October 2026, adds SceneDelegate support as an additive change with no user-facing breaking changes. RCTReactNativeFactory gets new entry points that take a window and the scene's connection options. Migration is three steps: move the React Native entry point from AppDelegate to a SceneDelegate, forward the scene's URL and user-activity callbacks to RCTLinkingManager, and add UIApplicationSceneManifest to Info.plist. Two limits matter: 0.88 supports a single scene only, so keep multiple scenes off, and at launch it forwards only the first URL context or user activity. The release notes also point out that with scenes the window is resizable, so Dimensions.get() and useWindowDimensions() now change at runtime.
Expo
Expo SDK 58, released on 16 October 2026 with React Native 0.88, uses the scene life cycle by default and npx expo prebuild generates SceneDelegate.swift. Expo's scene life cycle guide lists the catch: ExpoAppSceneDelegate routes URLs, user activities and quick actions back to your ExpoAppDelegate overrides, but code that assumed the app delegate owns the window needs changes. Teams that cannot move to SDK 58 yet can opt in on SDK 57 with ios.enableSceneSupport in expo-build-properties, which requires expo 57.0.23 or newer and the standard Swift AppDelegate. SDK 58 also notes that on iOS 27 requireFullScreen no longer opts an app out of resizing, and orientation locks may have no effect while the app is resizable.
Capacitor
Capacitor 8.5 adopts the scene life cycle as a breaking minor release, iOS only. For most projects npx cap migrate adds SceneDelegate.swift, the Info.plist entry and one AppDelegate method. The legacy URL notifications are still posted from the scene path, so most plugins keep working, and App.getLaunchUrl() still returns the launch URL.
Unity
Unity generates its own Xcode project, so check that the Unity version you ship on supports the scene life cycle before building with Xcode 27, and read your patch's iOS release notes. One concrete warning from Unity's issue tracker: UUM-135497 describes Application.deepLinkActivated not firing while the app is running once UIApplicationSceneManifest is in Info.plist. It is marked fixed in 6000.3.12f1, 6000.0.71f1 and 2022.3.75f1, but comments on the issue report universal-link problems in later patches, so test deep links on a device rather than assuming.
A migration checklist that works
This is the order we follow on client apps. It keeps the risky part, launch and links, on a branch until it is proven.
- Inventory. List every native dependency with lifecycle or window code: push, analytics, attribution, auth, payments, ads. For each, find the first version that mentions UIScene or iOS 27.
- Upgrade the framework first, on a branch: Flutter 3.41+, React Native 0.88, Expo SDK 58, or Capacitor 8.5. Run the official migrator where one exists.
- Move custom code. Anything that renders, presents or reads the screen moves to the scene delegate. Process-wide setup stays in
AppDelegate. - Replace window shortcuts.
UIApplication.shared.keyWindow,windowsandUIScreen.mainbecome scene-based lookups. The Flutter guide has a replacement table for these. - Build with Xcode 27 and test four launch paths on a real device: cold start from the icon, cold start from a universal link, cold start from a push notification tap, and a link opened while the app is already running. Deep links are where every framework above has had regressions.
- Test resizing. On iPad, try Full Screen, Windowed Apps and Stage Manager, as Apple recommends. Check layouts that assumed a fixed screen size.
- External displays. If your app shows custom content on an external display, Apple's guide explains that from iOS 27 the app receives that scene only after it registers a scene accessory.
- Ship through TestFlight, watch crash-free sessions and link analytics for a week, then release.
Our take
For a typical app that uses scenes only because Apple requires it, the code change is small: one new file, one Info.plist entry and some moved callbacks. The cost is in testing, because the bugs show up in launch paths that QA rarely covers, such as a cold start from a push tap or a universal link. We would not wait until March 2027. Plan it as a normal release this quarter, while Xcode 26 is still a fallback if something blocks you. The same work also prepares the app for resizable windows, which iOS 27 now applies to iPhone apps as well.
At Lightning Studio we maintain Flutter, React Native and Unity apps for clients, and this migration is now on every iOS roadmap we touch. If you want a second pair of eyes on your plugin list or a migration branch, we can help.
Sources
- Apple: Transitioning to the UIKit scene-based life cycle
- Apple: TN3187, Migrating to the UIKit scene-based life cycle
- Apple Developer News: App Store submissions now open for the latest OS releases (9 Sep 2026)
- Flutter docs: UIScene adoption
- React Native 0.88 release notes (19 Oct 2026)
- Expo SDK 58 changelog (16 Oct 2026) and Expo scene life cycle guide
- Capacitor: Updating to 8.5 and Ionic: Capacitor 8.5 Released
- Unity Issue Tracker: UUM-135497
Need help moving an iOS app to Xcode 27 or auditing a cross-platform project before the April 2027 deadline? Email us at support@lightning-studio.org or see what we build at Lightning Studio.
Cover photo: Laptop Programmcode by Negative Space, CC0 1.0, via Wikimedia Commons (cropped).



