Add a Scene Delegate to your current project
Tags: swift, ios
Published: 2019-10-28 14:26:58

---
title: Add a Scene Delegate to your current project
published: true
description: A quick tutorial on how to add a SceneDelegate to your existing iOS project, that might not be iOS 13 only.
tags: Swift, iOS
---

With iOS 13's introduced UIWindowScene and multiple window support for iPad OS, you might be looking to add Scene Delegate to your existing app (if you are willing to add support of multi window support, for example 😉).

Before iOS 13, the main entry point for your app was the AppDelegate, and it was in charge of many logic and state handling. Now the work of the AppDelegate has been split, between the AppDelegate and the SceneDelegate.

The AppDelegate being only responsible for the initial app setup, the SceneDelegate will handle and manage the way your app is shown.
As an app could have multiple instances, a SceneDelegate will be called every time an instance of your app is created.

To add a scene delegate, first, create a new Swift file that you’ll call "SceneDelegate" containing a subclass of `UIResponder`, just like the AppDelegate, and that conforms to `UIWindowSceneDelegate`. As your app might supports other versions than iOS 13, make this class only available for iOS 13.

This is what you should have :

```
//
//  SceneDelegate.swift
//
import UIKit

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
	// ...
}
```

To this class, add a `UIWindow` property. That will be your main window, you will need it to present your View Controllers.

```
var window: UIWindow?
```

Finally, you need to implement the SceneWillConnectToSession method in your class.
This method is the way that notifies us about the addition of a scene to the app, a scene could be seen as a window.

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

    }
```

###If you are working a project that is storyboard based,
you could leave this method empty.
That means that you have a `UIMainStoryboardFile` specified in your `info.plist` with a ViewController set as initial (with an arrow on it's side).

###If you are not working with a main storyboard,
you should have your view hierarchy set in you AppDelegate's `applicationDidFinishLaunchingWithOptions` method. Then you want to add the same code in your `SceneWillConnectToSession` function, and instead of working with a `UIWindow`, it's a `UIWindowScene` that will host your root.
You will also want to wrap your AppDelegates code into an `#available` check to make sur it wont be executed if your SceneDelegate does it.

So this is what you should have in your AppDelegate :
(ViewController being your app's "Home"/"Main")

```
	// AppDelegate
	
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if #available(iOS 13.0, *) { } else {
        	self.window = UIWindow(frame: UIScreen.main.bounds)
	        let mainViewController = ViewController()
	        let mainNavigationController = UINavigationController(rootViewController: mainViewController)
	        self.window!.rootViewController = mainNavigationController
	        self.window!.makeKeyAndVisible()
        }
        return true
    }
```
And in your SceneDelegate :
```
	// SceneDelegate
	
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }
        if let windowScene = scene as? UIWindowScene {
            self.window = UIWindow(windowScene: windowScene)
            let mainNavigationController = UINavigationController(rootViewController: viewController)
            self.window!.rootViewController = mainNavigationController
            self.window!.makeKeyAndVisible()
        }
    }
```

Finally, to make your app to use this Scene Delegate, you need to configure it as your main scene delegate. Just go in your `info.plist` file and add these lines :

```
<key>UIApplicationSceneManifest</key>
	<dict>
		<key>UIApplicationSupportsMultipleScenes</key>
		<true/>
		<key>UISceneConfigurations</key>
		<dict>
			<key>UIWindowSceneSessionRoleApplication</key>
			<array>
				<dict>
					<key>UISceneConfigurationName</key>
					<string>Default Configuration</string>
					<key>UISceneDelegateClassName</key>
					<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
					
					<!-- ONLY IF YOU HAVE A MAIN STORYBOARD -->
					<key>Storyboard Name</key>
					<string>Main</string>
				</dict>
			</array>
		</dict>
	</dict>
```

We make a SceneManifest in which we declare our SceneDelegate as being the default configuration for a scene.

![](https://thepracticaldev.s3.amazonaws.com/i/2usrv7e423eibhd2a9j6.png)

⚠️ If you have a Main storyboard don't forget to specify it in the `Storyboard Name` field. If you don't, just remove the lines.

And there you are!
Now, if you execute your app on iOS/iPad OS 13, it will use the SceneDelegate, for iOS 12 and under, it will use your good old AppDelegate!

Hope you enjoyed this quick post.
If you need any help, don't hesitate to ping me on [Twitter](https://twitter.com/kevinmaarek), or just leave a comment below! 😇

Happy coding!