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?

, and how they are put together? What is the difference between UIApplicationDelegate and UISceneDelegate ?

and ? 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 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 [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