Xcode 27 · Capacitor, Expo, React Native, Flutter
You updated to Xcode 27, rebuilt, and the app now dies the moment it starts. Nothing in your code changed. The console has the line above:
Application failed to launch: UIScene life cycle is required for apps built with this SDK.
Apple announced this a year ago. Since iOS 26, UIKit has logged UIScene lifecycle will soon be required. Failure to adopt will result in an assert in the future. in apps without scenes. Apple’s technote was more specific: “In the next major release following iOS 26, UIScene lifecycle will be required when building with the latest SDK; otherwise, your app won’t launch” (Apple, TN3187). That release is iOS 27.
Two details decide whether you are affected:
- The trigger is the SDK, not the device. An app built with Xcode 26 still launches on iOS 27. The same app built with Xcode 27 does not, until it adopts scenes. That is why apps already on the App Store keep working on iOS 27, and why the problem shows up the first time you build with the new Xcode.
- You can’t stay on Xcode 26 forever. Apple says that starting April 2027, iOS and iPadOS apps uploaded to App Store Connect “must be built with the iOS & iPadOS 27 SDK or later, and target iOS 15 or later” (Apple, Submit your apps).
Most framework pages cover their own framework only. This one covers Capacitor, Expo, React Native, Flutter, SwiftUI and UIKit, with what we saw when we built the templates ourselves.
How to tell if your app is affected
An app is affected when both are true: it was built with the iOS 27 SDK, and its Info.plist has no UIApplicationSceneManifest key. Check the built app, not the Info.plist in your source tree: Flutter, Expo and Xcode’s generated Info.plist settings can add keys at build time.
-
Find the built
.app. For a simulator build it is in Xcode’s DerivedData (Build/Products/Debug-iphonesimulator/YourApp.app), or wherever your build tool puts it. -
Check which SDK built it.
plutil -extract DTSDKName raw -o - Path/To/YourApp.app/Info.plistiphonesimulator27.1oriphoneos27.1means the iOS 27 SDK. Anything below 27 isn’t affected yet. -
Look for the scene manifest.
plutil -extract UIApplicationSceneManifest xml1 -o - Path/To/YourApp.app/Info.plistIf the app uses scenes, this prints the manifest. If it doesn’t,
plutilanswersCould not extract valueand exits with an error: that build won’t launch on iOS 27.plutil -p Path/To/YourApp.app/Info.plist | grep UIApplicationSceneManifestgives the same answer.
The other Xcode 27 error: deployment target 15.0
Before you even reach the launch error, Xcode 27 may refuse to build. Xcode 27 supports deployment targets from iOS 15.0, and a project or pod that targets anything lower fails with an error like this one, which we hit:
The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 14.0, but the range of supported deployment target versions is 15.0 to 27.1.x
Raise Minimum Deployments to iOS 15.0 or later on the app target, and in a CocoaPods project set platform :ios, '15.0' in the Podfile and run pod install again. If a pod still sets its own lower target, raise it in your Podfile’s post_install hook. In our test, Capacitor 7’s CocoaPods targets stopped here before the scene error appeared. iOS 15 is also the minimum Apple will accept from April 2027.
Capacitor and Xcode 27
The Capacitor docs say it directly: “Capacitor 8.5 adopts the iOS UIScene lifecycle. Xcode 27 requires it.” They also note that “the core library still supports the AppDelegate path, so updating the dependency alone won’t break your app”, which also means updating alone doesn’t fix it. Your project has to adopt scenes (Capacitor, Updating to 8.5).
-
On Capacitor 7, upgrade to 8 first. Follow Updating from Capacitor 7 to Capacitor 8: install the latest CLI, run
npx cap migrate, and set the iOS deployment target to 15.0 (platform :ios, '15.0'inios/App/Podfilefor CocoaPods projects). -
Update to 8.5.
npm i @capacitor/core@^8.5.0 @capacitor/ios@^8.5.0 npm i -D @capacitor/cli@latest npx cap migrateThe migrator applies the scene changes to projects that still have the template shape.
-
Hand-edited projects follow the manual steps. Capacitor’s guide says “projects with hand-rolled scene delegates or custom AppDelegate URL handling should follow the manual steps instead”: create
App/App/SceneDelegate.swift, add the scene manifest toInfo.plist, and add aconfigurationForConnectingmethod toAppDelegate.swiftthat setsSceneDelegateas the delegate class.
What we saw: the Capacitor 7.6.9 template, with its deployment targets raised to 15.0, built with Xcode 27.1, and iOS 27.1 refused to launch it with the error above. The Capacitor 8.5.3 template launched and filled the iPhone Duo’s inner screen. For building Capacitor apps without a Mac, see Capacitor and Ionic cloud builds.
Expo and Xcode 27: SDK 58, or enableSceneSupport on SDK 57
Expo’s SDK 58 changelog: “iOS 27 requires the UIKit scene-based life cycle”, and “npx expo prebuild now generates SceneDelegate.swift and a UIApplicationSceneManifest entry in Info.plist” (Expo, SDK 58). What you do depends on how your project manages ios/ (Expo, iOS scene-based life cycle):
- Continuous Native Generation (you don’t commit
ios/): upgrade to SDK 58 and runnpx expo prebuild --clean. Nothing else. - A hand-managed
ios/folder: Expo’s guide lists three changes: add aSceneDelegate.swiftthat subclassesExpoAppSceneDelegate, declare the scene manifest in Info.plist, and updateAppDelegateso it no longer creates the window. The quickest way to see the target state, Expo suggests, is to prebuild a scratch copy and diff it against yours. - A bare React Native app with Expo modules: run
npx install-expo-modules@latest, which migrates the project for SDK 58 and later. - Staying on SDK 57 for now: Expo backported the scene runtime to
expo@57.0.23. Opt in with theios.enableSceneSupportproperty ofexpo-build-properties, then runnpx expo prebuild --clean. It only edits the template AppDelegate; a customised one needs the hand-managed steps.
{
"expo": {
"plugins": [["expo-build-properties", { "ios": { "enableSceneSupport": true } }]]
}
}
Watch for libraries and custom code. Expo’s guide warns that UIKit no longer calls the app delegate’s URL, user-activity and foreground/background methods under scenes, so code that hooks UIApplicationDelegate directly outside ExpoAppDelegate stops firing, and code should stop reading UIScreen.main or UIApplication.shared.keyWindow. To build an Expo app for iOS without EAS or a Mac, see Expo builds without EAS.
React Native 0.88 and SceneDelegate
React Native 0.88, released on October 19, 2026, puts it plainly: “Starting with the iOS 27 SDK, Apple requires the UIScene lifecycle: UIKit apps built with Xcode 27 will fail to launch.” 0.88 adds SceneDelegate entry points to RCTReactNativeFactory and keeps the AppDelegate path working (React Native 0.88).
- New apps created from the community template already use a scene delegate.
- Existing apps make three changes, per the release post: move the React Native entry point from your
AppDelegateto aSceneDelegate; forward the scene’s URL and user-activity callbacks toRCTLinkingManager; add aUIApplicationSceneManifestkey toInfo.plist. Use the upgrade helper to compare yourSceneDelegate.swiftandInfo.plistwith the 0.88 template. - One scene only. Support in 0.88 is limited to a single scene, so keep
UIApplicationSupportsMultipleScenesset tofalse. - Libraries (not covered by the release post). Native modules that read the window or screen from the app delegate, or rely on app-delegate life-cycle callbacks, may need updates; Expo’s guide above describes the same problem from the Expo side. Check your native dependencies’ release notes.
With scenes the app window becomes resizable, and Dimensions.get() and useWindowDimensions() follow it. To build a React Native app for iOS without a Mac, see Build a React Native app without a Mac.
Flutter UIScene migration
Flutter’s docs: “As of the Flutter 3.41 release, UIScene support is the default for iOS apps, and eligible apps are migrated automatically” (Flutter, UISceneDelegate adoption).
- An unmodified AppDelegate migrates on its own the next time you run
flutter runorflutter build ios. The CLI printsFinished migration to UIScene lifecyclewhen it is done. - A custom AppDelegate, or a Flutter version before 3.41, migrates by hand: make
AppDelegateconform toFlutterImplicitEngineDelegateand register plugins indidInitializeImplicitFlutterEngine, and add the scene manifest to Info.plist withUISceneDelegateClassNameset toFlutterSceneDelegateor your own subclass of it (subclassing is recommended, not required). Flutter warns that reaching for theFlutterViewControllerinapplication:didFinishLaunchingWithOptions:may crash; use the implicit engine delegate instead.
What we saw: the Flutter 3.47.7 template built with Xcode 27.1, its built Info.plist contains the scene manifest, and it launched on iOS 27.1 with no changes. See Flutter cloud builds to build one yourself.
SwiftUI and Kotlin Multiplatform
An app whose entry point is @main struct YourApp: App already uses scenes, so there is nothing to change. That includes the Kotlin Multiplatform iOS template, whose app entry point is SwiftUI; our build of it with Xcode 27.1 launched on iOS 27.1. If you aren’t sure which entry point your app uses, run the check above.
Native UIKit apps
Apple’s TN3187 is the reference. A single-window app needs three changes.
-
Declare the scene manifest. In Xcode, select the app target, open General, and choose Scene manifest under Deployment Info, or add the key to Info.plist yourself:
<key>UIApplicationSceneManifest</key> <dict> <key>UIApplicationSupportsMultipleScenes</key> <false/> <key>UISceneConfigurations</key> <dict> <key>UIWindowSceneSessionRoleApplication</key> <array> <dict> <key>UISceneConfigurationName</key> <string>Default Configuration</string> <key>UISceneDelegateClassName</key> <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> </dict> </array> </dict> </dict> -
Create the window in a scene delegate. Move window creation out of
application(_:didFinishLaunchingWithOptions:)and into the scene delegate, withUIWindow(windowScene:):import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = RootViewController() window.makeKeyAndVisible() self.window = window } }If your root view controller comes from a storyboard, name the storyboard in the scene configuration instead and UIKit creates the window for you.
-
Move life-cycle and URL code. Foreground and background work moves from the app delegate to the scene delegate (
sceneWillEnterForeground(_:),sceneDidEnterBackground(_:)and the rest of TN3187’s table). URLs that open your app arrive inscene(_:openURLContexts:), and on a cold start in theconnectionOptionspassed toscene(_:willConnectTo:options:). Process-wide setup stays in the app delegate.
Other frameworks: check your framework’s release notes for UIScene support before you switch to Xcode 27.
How we tested
We built each template with Xcode 27.1 on VibeView cloud builds and opened each build on the iPhone Duo simulator running iOS 27.1, in October 2026.
| Template | Built with Xcode 27.1 | On iOS 27.1 |
|---|---|---|
| Capacitor 7.6.9 | Yes, after raising deployment targets to 15.0 | Refused to launch: UIScene life cycle is required for apps built with this SDK |
| Capacitor 8.5.3 | Yes | Launched, full screen on the Duo’s inner screen |
| Kotlin Multiplatform (SwiftUI entry point) | Yes | Launched |
| Flutter 3.47.7 | Yes, scene manifest in the built Info.plist | Launched, full screen on the Duo’s inner screen |
We tested templates, not production apps. A real project with a customised AppDelegate, extra native modules or its own URL handling is where the manual steps above matter.
Check your app on iOS 27 without updating your Mac
Switching your own Mac to Xcode 27.1 changes every project on it at once, and your Mac may not run it. On VibeView you can try it on one project:
- Build with Xcode 27.1 in the cloud. Add
"xcode": "27.1"to the iOS build block invibeview.json, or runvibeview build --cloud --xcode 27.1for a single build (CLI 0.48.0 or later). The default stays Xcode 26.5. - See the problem before you open the app. VibeView flags an iOS build made with the iOS 27 SDK that doesn’t use the scene life cycle: on the cloud build’s page, as a won’t launch on iOS 27 badge in Build history, in the output of
vibeview buildandvibeview upload-app(CLI 0.49.0 or later), and on the Devices page when you open the build on iOS 27. It checks builds you upload as well as cloud builds. - Open it on an iOS 27 simulator in your browser, including the iPhone Duo, and watch it launch, or not.
Cloud Builds: Prepare your app for the iOS 27 SDK has the reference, and Build for iPhone Duo with Xcode 27.1 walks through a build end to end.
Frequently asked questions
What does "UIScene life cycle is required for apps built with this SDK" mean?
Your app was built with the iOS 27 SDK (Xcode 27) and doesn’t use the scene-based life cycle, so iOS 27 won’t launch it. Adopt scenes: Capacitor 8.5 with npx cap migrate, Expo SDK 58, React Native 0.88, Flutter 3.41 or later, or a scene delegate and scene manifest in a UIKit app.
Does it affect apps already on the App Store?
Not by itself. The rule depends on the SDK an app was built with, so a build made with Xcode 26 keeps launching on iOS 27. It affects your next build with Xcode 27, and Apple requires the iOS 27 SDK for App Store Connect uploads from April 2027.
Does an app built with Xcode 26 run on iOS 27?
Yes. iOS 27 only refuses apps built with the iOS 27 SDK that don’t use scenes. A build made with Xcode 26 launches on iOS 27 with the old life cycle.
Why does my app crash at launch after updating to Xcode 27?
The most likely cause is the missing scene life cycle: check the built app’s Info.plist for UIApplicationSceneManifest as shown above. If Xcode 27 won’t build the project at all, check the deployment target first: Xcode 27 needs iOS 15.0 or later.
Does it affect Apple TV (tvOS) apps?
We haven’t verified tvOS, so we can’t say yet. If you ship a tvOS app, read Apple’s TN3187 and launch a build made with Xcode 27 before you release it.
Do SwiftUI apps need to change anything?
No. An app with a @main SwiftUI App struct already uses scenes. That includes the Kotlin Multiplatform iOS template, which launched on iOS 27.1 in our test.
Related guides
In the documentation
Try it yourself
Open a live iOS simulator, Android emulator, Apple TV, Android TV or Roku in your browser.
Start free