iOS 13 (iPadOS) App Life Cycle with UIScene, Scene Session and Scene Delegate
The introduction of multi-window support on iOS 13 (iPadOS) brings major changes in application’s life cycle. This alters the ways we used to manage app state, create windows and respond to system events. The update comes with the new concept of a scene. Understanding how scenes are put together is a fundamental part of the modern iOS app model. In this article let’s find out:
- What are
UIScene
,UISceneSession
and how they are put together? - What is the difference between
UIApplicationDelegate
andUISceneDelegate
? - What is the life cycle of a scene and scene session?
- How to respond to the scene and scene session life cycle events?
Defining Scene and Scene Session
Scene is a single instance of your app’s user interface. A scene is represented with a UIScene
object. Typically, you use UIWindowScene
to take care of one or more windows where you put your UI, and the life cycle of that scene as the user interacts with it [1].
Scene session is the model representation of a scene. It contains scene configuration and the persisted interface state that the user were doing last. The system uses sessions to manage scenes in your app, so that the scenes can be connected and disconnected from their sessions.
We cannot directly create and destruct scenes. Instead, we can only request UIApplication
to do this for us and react to it in our scene delegate. Additionally, the system may create scenes in response to user interactions with the app, e.g. drag-and-drop.
Scene Delegate and App Delegate
Although we cannot create scenes, we have lots of flexibility at our disposal with regards to their management. This is done with the help of app delegate and scene delegate.
Starting with iOS 13 (iPadOS), UIApplicationDelegate
is responsible for configuring and discarding scenes. The methods .configurationForConnecting
and .didDiscardSceneSessions
are mandatory to implement in your app delegate.
Scene delegate manages life cycle events and state restoration of your app on per-scene basis. Typically, your scene delegate will conform to UIWindowSceneDelegate
protocol to be able to manage windows. The window
property of your scene delegate replaces the deprecated keyWindow
property of UIApplication
, which was stored in the UIApplicationDelegate
subclass. Same as with scenes, you cannot instantiate a scene delegate object directly. Instead, you must specify its class name in Info.plist
or pass one dynamically during scene session configuration.
UISceneDelegate
takes over the UI-related responsibilities ofUIApplicationDelegate
. This leaves app delegate responsible for application and scene sessions life cycles. I am touching on the subject in Refactoring Massive App Delegate.
UIScene Life Cycle
Given it’s alive, a scene can be in one of these states [2]:
- Unattached
- Suspended
- Background
- Foreground: Active or Inactive
1 Unattached
The scene always starts in the unattached state. It has two routes from here. If requested by a user, it goes into the foreground state. If requested by the system, it stays in the background to process an event.
The system may detach the scene from the background or suspended states at any time to reclaim its resources.
Although scenes may come and go, their sessions always will be there available.
Use following methods in your UISceneDelegate
to respond to scene being attached and detached:
2 Suspended
In the suspended state the scene is not performing any work and can be considered sleeping. The scene may be detached or woken up from this state. When woken up, the scene moves into the background to process certain tasks, which we will discuss in a moment.
The system may suspend the scene at any time when it’s in the background.
Scene delegate is not notified when the scene becomes suspended.
3 Background
In the background state the scene is not visible to the user and is limited in tasks it’s allowed to perform. From the background state the scene may take 3 different routes: become unattached, become suspended and move to the foreground.
Here are some tasks that the scene can perform from the background: bluetooth communication, location updates, push notifications, UIApplicationShortcutItem
, NSUserActivity
like handoff. Some of these are initiated by the app via BackgroundTasks
. The others are delivered by the system.
We can specify which scene wants to be targeted by system events. This is done by setting
UISceneActivationConditions
during scene session configuration.
The following sequence of methods is called on UISceneDelegate
when a user moves the scene to the background by swiping it up:
- Move to foreground-inactive:
sceneWillResignActive(_:)
. - Move to background:
sceneDidEnterBackground(_:)
. - If not processing any tasks:
sceneDidDisconnect(_:)
.
4 Foreground
In the foreground state the scene is presented to the user. It has two sub-states: active and inactive.
The scene is processing system and user interaction events when it’s foreground-active. The scene may become inactive when it’s interrupted, e.g. by a phone call, or because it is transitioning to or from the background. When foreground-inactive, the scene is not receiving system and user interaction events.
When transitioning to the foreground, the following methods are called:
- The scene is about to become visible onscreen:
sceneWillEnterForeground(_:)
- The scene is ready to respond to user events:
sceneDidBecomeActive(_:)
When transitioning to the background:
- The scene is about to stop responding to user events:
sceneWillResignActive(_:)
- The scene is no longer visible onscreen:
sceneDidEnterBackground(_:)
In case of interruption, the scene may fluctuate between the active and inactive states, without entering the background:
sceneDidBecomeActive(_:)
,- and
sceneWillResignActive(_:)
.
UISceneSession Life Cycle
The life cycle of scene sessions is handled by UIApplicationDelegate
. The system notifies it when a new session is created, or an existing one is discarded:
- Configure a new scene session for the first time:
application(_:configurationForConnecting:options:)
. - The scene is dismissed permanently by a user:
application(_:didDiscardSceneSessions:)
.
Another significant event in scene session life cycle is state restoration. When the system is about to detach the scene, it asks your scene delegate to provide a state via stateRestorationActivity(for:)
. It will be copied in scene session’s stateRestorationActivity
property. This information should be used to restore the scene to its previous state when it’s re-connected.
Further Reading
Thanks for reading!
If you enjoyed this post, be sure to follow me on Twitter to keep up with the new content. There I write daily on iOS development, programming, and Swift.