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
UISceneSessionand how they are put together?
- What is the difference between
- 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 .
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
.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.
UISceneDelegatetakes over the UI-related responsibilities of
UIApplicationDelegate. 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 :
- Foreground: Active or Inactive
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:
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.
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,
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
UISceneActivationConditionsduring 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:
- Move to background:
- If not processing any tasks:
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:
- The scene is ready to respond to user events:
When transitioning to the background:
- The scene is about to stop responding to user events:
- The scene is no longer visible onscreen:
In case of interruption, the scene may fluctuate between the active and inactive states, without entering the background:
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:
- The scene is dismissed permanently by a user:
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.
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.