What does state restoration restore, and how do you make an app survive being killed in the background?
Predict first
When should you write the user’s current screen state to disk?
// A: in applicationWillTerminate
// B: when the scene enters the background
// C: only at launch
- A
- B
- C
Mental model. A bookmark in a book. The book (your data) is kept separately; the bookmark just lets the reader land on the right page.
The system may terminate a backgrounded app at any time to reclaim memory, and the user will still expect to return to what they were doing. State restoration makes that work. Restoration is about where the user was (the screen, scroll position, a half-typed draft), not about your data model, which you persist normally.
The modern approach is per scene. Implement stateRestorationActivity(for:) on the scene delegate to return an NSUserActivity describing the current screen and its userInfo; the system saves it when the scene goes to the background and hands it back in scene(_:willConnectTo:options:) on the next launch. In SwiftUI use @SceneStorage for small per-scene values (selected tab, text) and @AppStorage for defaults. Keep what you restore small and quick to rebuild, never block the first frame to restore it, and validate it (the item may have been deleted). Test by backgrounding the app and killing it from Xcode, or by simulating memory pressure, rather than relying on the happy path.
A suspended app is killed without callback, so the safe moment is when it goes to the background.
Common traps
- Saving only in
willTerminate. It is not called for a suspended app. Save when the scene enters the background. - Restoring heavy state synchronously at launch. It delays the first frame. Restore the screen, then load data.
They might follow up with
- How do you test it? Background the app, then terminate it from Xcode or the app switcher, and relaunch; also test with a debugger’s memory-pressure simulation.
- What about data? Persist it eagerly and independently; restoration should only point at it.
Related questions
- 6.2.1 What are the app states, and which callbacks fire as you move between them?
- 6.2.2 What is a scene, and what is the split between AppDelegate and SceneDelegate?
- 6.6.2 What is jetsam, and how does it differ from a crash?
← How does the SwiftUI lifecycle map onto UIKit’s, and what is…