What is the App protocol, what are scenes, and what does scenePhase tell you?
Predict first
On iPad the user opens a second window of the same WindowGroup. Is the first window’s @State shared with it?
// A: yes, it is the same root view
// B: no, each scene gets its own view hierarchy and state
// C: only for @State marked static
- A
- B
- C
Mental model. A scene is one window onto the app. Each window has its own page open, while the app’s shared data sits behind all of them.
A SwiftUI app is a type marked @main that conforms to App and returns a Scene from its body. A scene is a unit the system can show and manage independently: WindowGroup (one or more windows with the same content, which on iPad and Mac can be several at once), Window and DocumentGroup for single windows and document apps, Settings on Mac, and others per platform. Each scene has its own view state, so with two windows open you have two independent copies of the root view and its @State; share data through a model that lives above the scenes (in the app struct).
@Environment(\.scenePhase) reports .active, .inactive or .background for the scene (and, read in the App, the aggregate of all scenes). React with .onChange(of: scenePhase): save in .background, refresh on .active. Because it is a scene-level signal, it replaces many app-delegate callbacks, and for things SwiftUI does not cover (push registration, some launch options) you attach a UIKit app delegate with @UIApplicationDelegateAdaptor. Persist the state that should survive termination with @SceneStorage (per scene) or @AppStorage (UserDefaults). The mapping to UIKit’s UIScene lifecycle is covered in the platform topic.
Each scene builds its own copy of the content. Share data with a model owned above the scenes.
Common traps
- Putting shared data in the root view’s
@State. Each new scene gets its own copy; hold shared models in theApp. - Saving only on
.inactive. It also occurs for brief interruptions; save on.background.
They might follow up with
- How do you handle push registration? Use
@UIApplicationDelegateAdaptorto attach an app delegate. - What is
@SceneStorage? Per-scene state that the system restores when the scene returns.
Related questions
- 8.4.1 When do onAppear, task and onChange run, and which one do you use for async work?
- 6.2.1 What are the app states, and which callbacks fire as you move between them?
- 6.2.4 How does the SwiftUI lifecycle map onto UIKit’s, and what is scenePhase for?
← When do onAppear, task and onChange run, and which one do you use for…