Guides7 min read

iOS 27 makes UIScene mandatory

Apps built with the iOS 27 SDK must adopt the scene-based lifecycle or they do not launch at all. What Capacitor 8.5 changed, the two-command migration, and where it goes wrong.

There is a specific error waiting for iOS developers this autumn, and it is not subtle:

Application failed to launch: UIScene life cycle is required
for apps built with this SDK

Not a crash on a screen. Not a degraded feature. The app does not start. Apps built against the iOS 27 SDK must adopt the scene-based lifecycle, and one built without it terminates at launch on every device it reaches. Capacitor apps are not exempt — and neither is any other web-to-native framework, as Expo's own bug reports from the Xcode 27 betas show.

Who is affected right now: only builds compiled with the iOS 27 SDK, which means Xcode 27. An app already on the App Store, built with Xcode 26, keeps running on iOS 27 devices exactly as before. This is a build-time cliff, not a device-side one — which is precisely why it catches teams the first time they open the new Xcode.

Why Apple did this

UIApplicationDelegate-driven startup dates from single-window iPhones. Scenes, added in iOS 13, model an app as one or more UI instances the system can create, background and discard independently — the model iPadOS multitasking, Stage Manager, CarPlay and visionOS already assume. Apple has been asking for seven years; with the iOS 27 SDK it stopped asking. The migration reference is Apple's Technote TN3187.

The practical consequence people miss: an app that will not launch cannot receive a push notification, cannot run a background refresh, and cannot report a crash. Every telemetry signal you would normally use to notice a problem goes quiet at the same moment.

The Capacitor migration is two commands

Capacitor 8.5, released 31 July 2026, adopted UIScene. Ionic shipped it as a breaking minor specifically so the migration would land before the iOS 27 SDK became unavoidable. Update the CLI and run the migrator:

npm i -D @capacitor/cli@latest
npx cap migrate

What it changes on the iOS side is small and worth reading in the diff: a UIApplicationSceneManifest entry in Info.plist, a scene delegate wired to Capacitor's bridge, and the app delegate's window handling moved to the scene. The official notes are at capacitorjs.com/docs/updating/8-5, and Ionic also ships a capacitor-uiscene-migrator agent skill for projects the automated path does not fully handle.

Where it goes wrong

  • A custom AppDelegate. If you added push handling, deep-link routing or third-party SDK bootstrapping to AppDelegate.swift, the migrator will not always know which callbacks belong on the scene. Lifecycle callbacks (applicationDidBecomeActive and friends) move; process-level ones (didFinishLaunchingWithOptions) stay.
  • Plugins that assume a key window. Anything reaching for UIApplication.shared.windows.first is on borrowed time. Update the plugin, or read the window from the connected scene.
  • Deep links and universal links. Cold-start URL delivery arrives through the scene's connection options rather than the app delegate. Test the cold path, not just the warm one — see deep links in Capacitor.
  • Push notification taps. Same story: the launch-from-notification path is the one that silently stops working, and it is the one nobody re-tests.

How much time do you actually have?

Apple's current floor, in force since 28 April 2026, is the iOS 26 SDK or later for anything uploaded to App Store Connect. So you are not yet compelled onto Xcode 27, and an app built with Xcode 26 can still be submitted today.

That is the letter of it. In practice the timer is shorter than the letter suggests: Apple raises the floor roughly every spring, Xcode 27 is Apple-silicon only, and the day you need to debug something that only reproduces on iOS 27 you will need the new SDK anyway. Treat 8.5 as work for this quarter rather than next. Do it while nothing is on fire and it is a routine merge; do it under a deadline and it is an outage.

This is the honest limit of over-the-air updates. A launch-time native failure cannot be repaired from the web layer — if the app terminates before the WebView exists, there is nothing to update. Ship the UIScene migration as a store build. OtaKit covers what comes after: the web-layer fallout from a native upgrade, shipped the same day instead of the next review cycle. See rollback strategies for the safety net.

A migration order that works

  • Upgrade to Capacitor 8.5 or later and run npx cap migrate on a branch.
  • Build with Xcode 27 and launch on an iOS 27 simulator. It either starts or it does not — a fast, binary signal.
  • Re-test cold start from a push notification and from a universal link.
  • Audit plugins for UIApplication.shared.windows usage.
  • Ship it as a normal release, ahead of any deadline, with nothing else in the build.

Where to go next

Apple's Xcode and SDK requirements covers the submission floor and how CI trips over it, and the SPM migration guide covers the other iOS housekeeping worth clearing this year.

Related docs