What is the role of the SceneDelegate class in the iOS13 project? Since XCode 11, SceneDelegate is created by default when you create a new iOS project with new XCode, what does it really do?

In this article, we’ll delve into some of the changes to iOS 13 and Xcode 11. We’ll focus on SceneDelegate and AppDelegate and how they affect SwiftUI, Storyboard, and XIB-based UI projects.

By reading this article you will learn:

  • New changes to SceneDelegate and AppDelegate
  • How did they collaborate to guide your app launch
  • Used in pure handwriting AppSceneDelegate
  • Used in Storyboards and SwiftUI projectsSceneDelegate

Let’s get started.

This article is based on Xcode 11 and iOS 13.

AppDelegate

You might be in AppDelegate already familiar with, he is access to the iOS app application (_ : didFinishLaunchingWithOptions:) is your app starts the first function of the system call.

The AppDelegate class implements the UIApplicationDelegate protocol in the UIKit library. In iOS13, the role of the AppDelegate will change, and we’ll talk more about that later.

Here’s what you typically do in an AppDelegate in iOS12:

  • The first ViewController that you create your app is rootViewController
  • Configure and start components like logging and cloud services
  • Sign up for a push notification handler and respond to push notifications sent to your app
  • Responding to application life cycle events, such as going into the background, resuming the application, or exiting the application (termination)

In iOS12 and before, with Storyboards apps, the app delegate was very simple. Like this:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
    return true
}
Copy the code

A simple application using XIB would look like this:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{   
    let timeline = TimelineViewController(a)let navigation = UINavigationController(rootViewController: timeline)

    let frame = UIScreen.main.bounds
    window = UIWindow(frame: frame) window! .rootViewController = navigation window! .makeKeyAndVisible()return true
}
Copy the code

In the above code, we create a ViewController and place it in the Navigation Controller. And then assign it to the rootViewController property of the UIWindow object. This window object is an AppDelegate property, which is a window for our application.

The window of an application is an important concept. Essentially, a window is an application, and most iOS apps have only one window. It contains your application’s user interface (UI), schedules events to views, and provides a primary background layer to display your application content. In a sense, the concept of “Windows” is Microsoft’s definition of a window, and on iOS, the concept is no different. (Thank you, Xerox!)

Okay, let’s move on to SceneDelegate.

If the concept of “window” is still a mystery, check out the app switcher on your iPhone. Double-click the Home button or swipe up from the bottom of the iPhone, and you’ll see a window of the currently running apps. This is the application switcher.

The Scene Delegate

On iOS 13 (and later), SceneDelegate will take care of some of the AppDelegate functionality. Most importantly, the concept of window has been replaced by the concept of scene. An application can have more than one scene, and a scene can now serve as a vehicle (background) for your application’s user interface and content.

In particular, the concept of an App with multiple scenes is interesting because it allows you to build multi-window applications on iOS and iPadOS. For example, each text document in a document editor App can have its own scene. Users can also create copies of scenarios that run multiple instances of an application at the same time (similar to multi-open).

SceneDelegate is visible in three places in Xcode 11:

  1. Now, a new iOS project automatically creates oneSceneDelegateClass, which includes familiar lifecycle events such as active, resign, and Disconnect.
  2. The AppDelegate class has two new methods related to scene sessions:application(_:configurationForConnecting:options:)application(_:didDiscardSceneSessions:)
  3. The info.plist file provides the “Application Scene Manifest” configuration item, which is used to configure the App’s scenes, including their Scene configuration names, delegate class names, and storyboards

Let’s take one at a time.

1. Scene Delegate Class

First, the SceneDelegate class:

The most important function of SceneDelegate is scene(_:willConnectTo:options:). To some extent, it has to do with the iOS application on 12 (_ : didFinishLaunchingWithOptions:) function the role of the most similar. The scene(_:willConnectTo:options:) function will be called when adding a scene to the app, so this is an ideal place to configure the scene. In the code above, we manually set up the view controller stack, which we’ll cover in more detail later.

It’s important to note here that “SceneDelegate” uses protocol mode, and the delegate will usually respond to any scenario. You use a Delegate to configure all the scenarios in your App.

SceneDelegate also has the following functions:

  • sceneDidDisconnect(_:)Is called when the scene is disconnected from the app (note that it may be reconnected later)
  • sceneDidBecomeActive(_:)Called when the user starts interacting with the scenario (for example, selecting a scenario from the application switcher)
  • sceneWillResignActive(_:)Called when the user stops interacting with the scenario (for example, switching to another scenario through a switcher)
  • sceneWillEnterForeground(_:)Called when the scene becomes an active window, that is, from the background state to the start or resume state
  • sceneDidEnterBackground(_:)Called when the scene goes into the background, that is, the application has been minimized but is still alive in the background

See the symmetry of the function? Active/inactive, background/foreground, and “Disconnect”. These are typical life cycle events for any application.

2. Scene Sessions in App Delegate

In iOS13 there are two delegate functions that manage Senen sessions in AppDelegate. After your application creates a scene (scene), the Scene Session object keeps track of all information related to that scene.

The two functions are:

  • Application: (_ configurationForConnecting: options:), returns a scene need to create the UISceneConfiguration object

  • Application: (_ didDiscardSceneSessions:), when the user through the application switcher close one or more of the scene will be invoked

Currently, SceneSession is used to specify scenarios, such as “external display” or “CarPlay”. It can also be used to restore the state of a scene. If you want to use State Restore, SceneSession is very useful. State restoration allows you to preserve and recreate the UI between application startup. You can also store user information in a scene session, which is a dictionary that you can put into anything.

Application: (_ didDiscardSceneSessions:) is simple. This method is called when the user closes one or more scenarios through the Application switcher. You can destroy the resources used by the scenario in this function because they are no longer needed.

Understand application (_ : didDiscardSceneSessions:) and sceneDidDisconnect (_) distinction is important, the latter in disconnected scenario calls when alone, will not be discarded, it may be possible to reconnect. Application (_ : didDiscardSceneSessions:) occurs when exiting the scene using the Application Switcher.

3. Application Scene Manifest in info.plist

Each scenario supported by your Application needs to be declared in the Application Scene Manifest. In short, the listing lists each scenario that your application supports. Most applications have only one scenario, but you can create more scenarios, such as specific scenarios for responding to push notifications or specific actions.

The Application Scene Manifest is an entry in the info.plist file, which is known to contain configuration information for the App. Info.plist contains configurations such as the name of the App, version, supported device directions, and different scenarios now supported.

It is important to note that you are declaring the “type” of the session, not the session instance. Your application can support a scenario and then create a copy of that scenario to implement a multi-window application.

Let’s look at some of the configurations listed in info.plist:

In the red box, you’ll see the Application Scene Manifest. Underneath it is Enable Multiple Windows, which needs to be set to YES to support Multiple Windows. Further down, the value of the Application Session Role is an array used to declare scenarios in the Application. You can also add an external screen scene declaration to the array.

The most important information is stored in the Application Session Roles array. We can see the following:

  • The name of Configuration must be unique
  • The proxy class name for the scenario, usuallySceneDelegate.
  • The storyboard name used by the scene to create the initial UI

The name of the Storyboard may remind you of the Main Interface setting, which can be found in the Project Properties configuration of the Xcode 12 Project. Now, in iOS apps, you can set or change the main Storyboard name here.

How do AppDelegate SceneDelegate, UISceneSession, and Application Scene Manifest work together to create a multiwindow Application?

  • First of all, let’s seeSceneDelegateClass. It manages the life cycle of scenarios, handling responses such assceneDidBecomeActive(_:) and sceneDidEnterBackground(_:)Things like that.
  • And then, let’s seeAppDelegateClass for a new function. It manages scene sessions, provides configuration data for the scene, and responds to events when the user discards the scene.
  • Finally, we took a lookApplication Scene Manifest. It lists the scenarios supported by your application, connects them to the Delegate class and initializes the Storyboard.

Awesome! Now that we’ve got a playing field, let’s find out how scenes affects building UIs in Xcode 11.

That’s great! Now let’s see how scenes affect the user interface in Xcode 11.

Use Scene Delegate in SwiftUI

SwiftUI will be the easiest way to create iOS 13 projects in the near future. In short, the SwiftUI application relies primarily on SceneDelegate to set up the initial UI of the application.

First, the SwiftUI project “Application Scene Manifest” will look like this:

Note that the “Storyboard Name” item is not set in the configuration. Keep in mind that if you want to support Multiple Windows, you need to set Enable Multiple Windows to YES.

We’ll skip “AppDelegate” because it’s pretty standard. In the SwiftUI project, only “true” is returned.

Next up is the SceneDelegate class. As we discussed earlier, SceneDelegate is responsible for setting up the scene in your application, as well as setting up the first page.

Like the following:

class SceneDelegate: UIResponder.UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        let contentView = ContentView(a)if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
}
Copy the code

What happened in the code above?

  • First, it must be clear that the new scenario is called after it is added to the applicationScene (_ : willConnectTo: options:)Proxy functions. It provides onesceneObject (and a session). The “UIWindowScene” object is created by the application and you don’t need to do anything else.
  • Second,windowProperties are used here. The App still uses “UIWindow” objects, but now they are part of the scene. inif letIn the code block, you can clearly see how to use itsceneTo initialize the UIWindow object.
  • And then I’m going to set the Window rootViewControllerwindowThe instance is assigned to the scenewindowProperty, and set the windowmakeKeyAndVisibleTrue puts the window in front of the App.
  • You then create the ContentView instance for the SwiftUI project and add it as the root view controller using UIHostingController. This controller is used to display swiftui-based views on the screen.
  • Last but not least, it’s worth noting that UIScene’s instantiation object scene is actually an object of type UIWindowScene. This is theas?Reasons for casting optional types. (The scenes created so far are usually of the “UIWindowScene” type, but I suspect we’ll see more in the future.)

All of this may seem complicated, but from a high-level overview, it’s simple:

  • whenScene (_ : willConnectTo: options:)When called, SceneDelegate configures the scene at the correct time.
  • The default configuration of the AppDelegate and Manifest, they don’t involve anything in the storyboard.
  • Scene (_ : willConnectTo: options :)Within the SwiftUI function, create a SwiftUI view, place it in the managed controller, assign the controller to the root view controller of the Window property, and place the window in front of the application UI.

That’s great! Let’s move on.

You can set up a basic Xcode 11 Project by selecting File →New →Project. Then, select the Single View App and select SwiftUI in the User Interface to create a SwiftUI project

Use SceneDelegate in your Storyboards project

Storyboards and XIB are effective ways to build UIs for iOS applications. The same is true on iOS 13. We will see more SwiftUI applications in the future, but for now, Storyboards are more common.

Interestingly, even with SceneDelegate, you don’t need to do anything extra to create iOS projects from Storyboards just go to File → New → Project. Then, select the Single View App. Finally, select the Storyboard for the User Interface, and you’re done.

The setting method is as follows:

  • As we mentioned earlier, you can find it in the “Application Scene Manifest” in info.plistMainWhere the storyboard is set up.
  • By default, the AppDelegate will use the default UISceneConfiguration.
  • SceneDelegate sets a “UIWindow” object and uses “main.storyboard” to create the initial UI.

Write the UI in pure code

Many developers prefer handwritten UIs, and with the rise of SwiftUI, using SwiftUI handwritten code will become more and more common. What if instead of using Storyboards, you use XIB to create your application UI? Let’s see how SceneDelegate changes.

First, keep the default values in the AppDelegate and Application Scene Manifest. We don’t use storyboards, so we need to set the initial view controller in the scene(_:willConnectTo:options:) function of the SceneDelegate class.

Something like this:

class SceneDelegate: UIResponder.UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
    {
        if let windowScene = scene as? UIWindowScene {

            let window = UIWindow(windowScene: windowScene)
            let timeline = TimelineViewController(a)let navigation = UINavigationController(rootViewController: timeline)
            window.rootViewController = navigation

            self.window = window
            window.makeKeyAndVisible()
        }
    }
}
Copy the code

The code above is very simple and we won’t go into it in detail.

Simple, right? The core of using SceneDelegate is to move some code from the AppDelegate to SceneDelegate and properly configure the Application Scene Manifest.

Want to add scene support to your existing iOS projects? Can look at the Apple official documentation at https://developer.apple.com/documentation/uikit/app_and_environment/scenes/specifying_the_scenes_your_app_s Upports.

By Reinder de Vries

Le Coding


This is the end of the article, for the latest Swift related articles and cutting-edge information, please follow the public account: Le Coding.