Walk through the iOS app lifecycle — AppDelegate/SceneDelegate vs the SwiftUI App protocol
iOS moved from one AppDelegate owning the whole app, to per-window SceneDelegates, to SwiftUI's three-case scenePhase — each step trading granularity for simplicity.
LEARN BY DOINGPut your intuition to work3 steps
Walk through the iOS app lifecycle — AppDelegate/SceneDelegate vs the SwiftUI App protocol
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.This question is a filter for whether a candidate actually understands why the lifecycle looks the way it does, not just which method fires when. iOS has been through three eras: a single AppDelegate owning the whole app, a SceneDelegate splitting that ownership per window once multi-window iPad support arrived in iOS 13, and the SwiftUI App protocol that wraps both of those underneath a much smaller surface area. A senior answer connects all three rather than reciting whichever one they learned first.
#The single-AppDelegate era
Before scenes existed, one AppDelegate object represented the entire application's state machine, and its methods mapped directly onto what the user was doing to the app as a whole: application(_:didFinishLaunchingWithOptions:) fired once, at cold launch, to set up windows and dependencies; applicationWillResignActive(_:) and applicationDidBecomeActive(_:) bracketed anything that took the app out of the foreground without actually backgrounding it — an incoming phone call, the notification center being pulled down, the app switcher appearing; applicationDidEnterBackground(_:) and applicationWillEnterForeground(_:) bracketed the real background transition, which is where you saved state and had a limited number of seconds to finish outstanding work; and applicationWillTerminate(_:) was a best-effort, not-guaranteed callback for the rare case of the OS killing a foregrounded app outright.
#Scenes split that ownership up
iOS 13 introduced UIScene so a single app could own multiple windows — think an iPad app with two documents open side by side, each with its own independent lifecycle. AppDelegate kept the app-wide events: initial launch, vending a UISceneConfiguration for each new scene, registering for remote notifications, handling background URLSession completion. Everything about a particular window's foreground/background state moved to UISceneDelegate, one instance per scene: scene(_:willConnectTo:options:) replaces the old launch method for that scene, and sceneWillEnterForeground, sceneDidBecomeActive, sceneWillResignActive, and sceneDidEnterBackground mirror the old app-level callbacks but scoped to one window. A phone call no longer backgrounds "the app" in a meaningful sense — it resigns activity on whichever scene is currently key.
#The SwiftUI App protocol collapses the ceremony
A SwiftUI app declares @main struct MyApp: App, whose body returns a Scene — typically a WindowGroup — and that single declaration replaces both delegate objects for the common case. In place of six-plus granular callbacks, SwiftUI exposes exactly one signal through the environment: scenePhase, with exactly three cases — .active, .inactive, and .background. A view (or the App itself) reads @Environment(\.scenePhase) and reacts to it with .onChange(of: scenePhase), and that's usually enough to cover "save state when backgrounding" or "refresh data when returning to foreground."
That collapse is deliberate but lossy: scenePhase cannot tell you why you're inactive — a phone call, the app switcher, and a system permission alert all report .inactive identically, where UIKit's finer-grained callbacks at least gave you distinct entry points. When an app genuinely needs push notification delegate methods (UNUserNotificationCenterDelegate), custom URL scheme / universal link handling with full control, or background URLSession callbacks, SwiftUI still lets you bridge back to the old model with @UIApplicationDelegateAdaptor, attaching a conventional AppDelegate class to a SwiftUI App without giving up WindowGroup.