sceneDidEnterBackground is not called on iOS, swift - ios

I am implementing the iOS app with coordinator pattern and I need to show some privacy screen when the app enters background.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var coordinator: MainCoordinator?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = scene as? UIWindowScene else { return }
if let registry = DependencyResolver.shared as? DependencyRegistry {
DependencyGraph.setup(for: registry)
}
let navController = UINavigationController()
navController.setNavigationBarHidden(true, animated: false)
coordinator = MainCoordinator(navigationController: navController)
coordinator?.start()
self.window = UIWindow.init(windowScene: scene)
window?.rootViewController = navController
window?.makeKeyAndVisible()
}
func sceneWillEnterForeground(_ scene: UIScene) {
hidePrivacyProtectionWindow()
}
func sceneDidEnterBackground(_ scene: UIScene) {
showPrivacyProtectionWindow()
}
...
// MARK: Privacy Protection
private var privacyProtectionWindow: UIWindow?
private func showPrivacyProtectionWindow() {
guard let windowScene = self.window?.windowScene else {
return
}
privacyProtectionWindow = UIWindow(windowScene: windowScene)
let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "splash")
privacyProtectionWindow?.rootViewController = vc
privacyProtectionWindow?.windowLevel = .alert + 1
privacyProtectionWindow?.makeKeyAndVisible()
}
private func hidePrivacyProtectionWindow() {
privacyProtectionWindow?.isHidden = true
privacyProtectionWindow = nil
}
}
On entry, the sceneWillEnterForeground() is called. On going to background, sceneDidEnterBackground() is not called. What am I missing?

Found it myself in 10 minutes after posting the question, I used initially wrong methods. This will work for what I'm trying to achieve:
func sceneDidBecomeActive(_ scene: UIScene) {
hidePrivacyProtectionWindow()
}
func sceneWillResignActive(_ scene: UIScene) {
showPrivacyProtectionWindow()
}

Related

How to fix blank screen after deleting and re-installing my app

I am working on an app that requires users to log in or make an account to get to the main page. I used this code (below) in the SceneDelegate to basically tell the app that if the user is logged in, go to the main view controller, otherwise go to the login view controller. When the app is installed on a new device, this seems to work and once a user is logged in, the app takes them to the main view controller. However, I found that when the app is deleted and re-installed from a device, the app opens to a black view controller with an empty tab bar at the bottom. When I tried to debug by telling Xcode to print whether the app thinks it is signed in or not, in this case, it doesn't print that it's signed in OR out. Please let me know how to fix this if you know what the issue is. Heres the SceneDelegate code.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
if AuthManager.shared.isSignedIn {
// signed in UI
window.rootViewController = TabBarViewController()
print("signed in")
}
else {
// sign in ui
let vc = SignInViewController()
let navVC = UINavigationController(rootViewController: vc)
window.rootViewController = navVC
print("Sign IN")
}
window.makeKeyAndVisible()
self.window = window
}
func sceneDidDisconnect(_ scene: UIScene) {
}
func sceneDidBecomeActive(_ scene: UIScene) {
}
func sceneWillResignActive(_ scene: UIScene) {
}
func sceneWillEnterForeground(_ scene: UIScene) {
}
func sceneDidEnterBackground(_ scene: UIScene) {
}
}

After deleting Main Storyboard.Add StoryBoard Programatically with Backward compatibility

My target for app is iOS 10.0As soon as I change my Target, I get a bunch of errors in SceneDelegate file. For backward compatibility, I added “#available(iOS 13.0, *)” for Scene Delegate class.
I Started with an OnboardingController. Which is totally programatic. So I deleted MainStoryboard and removed it from ”Main Interface” and ”Application Scene Manifest” in info.
Now, I have to set the rootView in both AppDelegate and SceneDelegate. If I don’t set window in SceneDelegate I am getting only Black screen in iOS 13.0+ Devices and if I don’t set in AppDelegate I get just Black screen in <13.0 Devices
Since I am calling both files my viewdidload() in Viewcontroller is called twice.
Following is what my AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "navC") as! UINavigationController
window?.rootViewController = viewController
window?.makeKeyAndVisible()
return true
}
}
Following is my SceneDelegate
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeCollectionVC") as! HomeCollectionVC
window?.rootViewController = viewController
window?.makeKeyAndVisible()
}
...
}
am I missing something?
This can be found easily by searching, but here is an example...
Note: reference to SO user Matt
SceneDelegate.swift
import UIKit
// entire class is iOS 13+
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeCollectionVC") as! HomeCollectionVC
window?.rootViewController = viewController
window?.makeKeyAndVisible()
}
func sceneDidDisconnect(_ scene: UIScene) {
}
func sceneDidBecomeActive(_ scene: UIScene) {
}
func sceneWillResignActive(_ scene: UIScene) {
}
func sceneWillEnterForeground(_ scene: UIScene) {
}
func sceneDidEnterBackground(_ scene: UIScene) {
}
}
AppDelegate.swift
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?)
-> Bool {
if #available(iOS 13, *) {
// do only pure app launch stuff, not interface stuff
} else {
self.window = UIWindow()
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "navC") as! UINavigationController
window?.rootViewController = viewController
window?.makeKeyAndVisible()
}
return true
}
// MARK: UISceneSession Lifecycle
// iOS 13+ only
#available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
// iOS 13+ only
#available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

Updating/Changing root view controller after initially opening app for iOS13+

I'm trying to update the root view controller from ViewController() to fourYearPlan(). When the user initially opens the app, they are greeted in ViewController() and led to a TableViewController(). From there, when they tap on a tableViewCell, it will lead them to fourYearPlan() and automatically change the root view controller to it. If the user presses a button in fourYearPlan() the root view controller resets to ViewController(). How will I be able to approach this?
AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
updateRootVC()
return true
}
// MARK: UISceneSession Lifecycle
#available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
#available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
func updateRootVC(){
let status = UserDefaults.standard.bool(forKey: "status")
print(status)
if status == true {
let navController = UINavigationController(rootViewController: fourYearPlan())
window?.rootViewController = navController
}
else{
let navController = UINavigationController(rootViewController: ViewController())
window?.rootViewController = navController
}
window?.makeKeyAndVisible()
}
}
Portion of SceneDelegate:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window = window
appDelegate.updateRootVC()
}
ViewController() will lead to TableViewController() and if clicked, fourYearPlan becomes the new root view controller from ViewController():
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
tableView.deselectRow(at: indexPath, animated: true)
let layout = UICollectionViewFlowLayout()
let destination = fourYearPlan(collectionViewLayout: layout)
// UserDefaults.standard.set(true, forKey: "status")
// let appDelegate = UIApplication.shared.delegate as! AppDelegate
// appDelegate.updateRootVC()
navigationController?.pushViewController(destination, animated: true)
}
button in fourYearPlan() that resets root view controller:
#objc func addTapped(sender: UIBarButtonItem!) {
let addAlert = UIAlertController(title: "Start Over", message: "Are you sure you want to create a new plan?", preferredStyle: .alert)
addAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action:UIAlertAction) in
let defaults = UserDefaults.standard
// defaults.set(false, forKey: "status")
// let appDelegate = UIApplication.shared.delegate as! AppDelegate
// appDelegate.updateRootVC()
let domain = Bundle.main.bundleIdentifier!
defaults.removePersistentDomain(forName: domain)
defaults.synchronize()
let destination = ViewController()
self.navigationController?.pushViewController(destination, animated: true)
}))
addAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(addAlert, animated: true, completion: nil)
}
For Xcode 13+ , Swift 5+
Open SceneDelegate and paste replace this , Replace CustomerMainViewController with your view controller
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
if UserDefaultHelper.isLoggedIn! {
print("User logged in")
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) // this assumes your storyboard is titled "Main.storyboard"
let yourVC = mainStoryboard.instantiateViewController(withIdentifier: "CustomerMainViewController") as! CustomerMainViewController // inside "YOUR_VC_IDENTIFIER" substitute the Storyboard ID you created in step 2 for the view controller you want to open here. And substitute YourViewController with the name of your view controller, like, for example, ViewController2.
self.window?.rootViewController = yourVC
self.window?.makeKeyAndVisible()
}
else {
print("User Not logged in")
}
}

Update root view controller after user login + iOS 13 and later

Using scene delegate I'm able to set the root view controller.(I'm using Xcode 11.3 and iOS version 13.3 and running my app on iPhone 6+ with iOS 12.4)
What I want is when user login, I need to update the root view controller. For that I did the following
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
static let shared = SceneDelegate()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//some code is here
}
}
#available(iOS 13.0, *)
extension SceneDelegate {
func setRootViewControllerBasedOnLogin() {
if let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogin"), isLoggedIn {
let tabbar = UIStoryboard(name: "Other", bundle: nil).instantiateViewController(withIdentifier: "Tabbar") as! UITabBarController
if var vcs = tabbar.viewControllers {
vcs.remove(at: 2)
tabbar.viewControllers = vcs
}
self.window?.rootViewController = tabbar
} else {
//other stuff
}
}
}
So when user login in to the app I need to remove a tab item from tab bar and update the root view controller.
So I'm doing as follows.
func processLogin() {
//performing login in this method so when login successful we setting root view controller
callLoginAPI { response in
if response.isSuccess {
UserDefaults.standard.set(true, forKey: "isLogin")
if #available(iOS 13.0, *) {
SceneDelegate.shared.setRootViewControllerBasedOnLogin()
} else {
// Fallback on earlier versions
}
}
}
}
When I'm doing this nothing happened. I'm not able to change the root view controller of the app after user successfully login into the app?
Any suggestions? what am I doing wrong?
This is how I managed navigation for both the older version and the new version. So when the user has the latest iOS we need to setup root from sceneDelegate and for older version we need to setup root from appDelegate
AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
} else {
setupRoot()
}
return true
}
// MARK: UISceneSession Lifecycle
#available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
#available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
func setupRoot() {
//Setup Your Root Here
//window?.rootViewController = objNavigationVC
//window?.makeKeyAndVisible()
}
}
SceneDelegate.swift
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window = window
appDelegate.setupRoot()
}
}
func presentYourView(from view: YourViwe) {
if #available(iOS 13, *) {
let mySceneDelegate = view.view.window?.windowScene?.delegate
if let sceneDelegate = mySceneDelegate as? SceneDelegate {
sceneDelegate.changeRootViewController(newViewController())
}
} else {
(UIApplication.shared.delegate as? AppDelegate)?.changeRootViewController(newViewController())
}
}
Update Swift 5+ , Xcode 13+
To change rootViewController depending upon user has logged in or not, here is the full code for SceneDelegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
if UserDefaultHelper.isLoggedIn! {
print("User logged in")
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) // this assumes your storyboard is titled "Main.storyboard"
let yourVC = mainStoryboard.instantiateViewController(withIdentifier: "CustomerMainViewController") as! CustomerMainViewController // inside "YOUR_VC_IDENTIFIER" substitute the Storyboard ID you created in step 2 for the view controller you want to open here. And substitute YourViewController with the name of your view controller, like, for example, ViewController2.
self.window?.rootViewController = yourVC
self.window?.makeKeyAndVisible()
}
else {
print("User Not logged in")
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
The problem with PinkeshGjr's answer is that it discardings the window object provided by the scene. Here's what I feel is a better/simpler approach:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
static var current: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
} else {
window = UIWindow();
setUpRoot()
}
return true
}
func setUpRoot() {
window?.rootViewController = ViewController(nibName: nil, bundle: nil)
window?.makeKeyAndVisible()
}
}
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { fatalError() }
let firstWindow = windowScene.windows.first ?? UIWindow(windowScene: windowScene)
AppDelegate.current.window = firstWindow
AppDelegate.current.setUpRoot()
}
}

Set rootViewController iOS 13

After upgrading Xcode a critical part of my application has stopped working.
When my app launches I run a function to check boolean flags and set the correct rootViewController.
But the code I have been using to set this has now stopped working
class func setLoginAsInitialViewContoller(window:UIWindow) {
print("SET LOGIN")
let storyboard = UIStoryboard(name: "Login", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
controller.modalPresentationStyle = .overFullScreen
window.rootViewController = controller
window.makeKeyAndVisible()
}
Specifically when the app gets the the second last line window.rootViewController = controller it crashes with a libc++abi.dylib: terminating with uncaught exception of type NSException error.
The above function is in a class called Utilities.swift and I am calling the function from within my AppDelegate.swift as shown below:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var storyboard: UIStoryboard? = nil
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.isIdleTimerDisabled = true
Utilities.decideInitialViewController(window: self.window!)
return true
}
Any solutions or fixes on how I can set the root controller is much appreciated.
Thank!
This is because AppDelegate doesn't have window property anymore.
Now you must use SceneDelegate's scene(_:willConnectTo:options:) method to change root view controller.
Like shown in this example:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
// Instantiate UIWindow with scene
let window = UIWindow(windowScene: scene)
// Assign window to SceneDelegate window property
self.window = window
// Set initial view controller from Main storyboard as root view controller of UIWindow
self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
// Present window to screen
self.window?.makeKeyAndVisible()
}
It is available in SceneDelegate.swift file in your project
It will have delegate method :
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions)
Example
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let initialViewController =
storyboard.instantiateViewController(withIdentifier: "FirstViewController")
self.window!.rootViewController = initialViewController
self.window!.makeKeyAndVisible()
}
}
In viewDidAppear you can set root:-
override func viewDidAppear(_ animated: Bool) {
print(self.view.window)
let vc = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController
self.view.window?.rootViewController = vc
}
For anyone looking to create a couple of extensions to change the root view controller and need to support both delegate types (UISceneDelegate and AppDelegate), here's a couple:
extension UIViewController {
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var sceneDelegate: SceneDelegate? {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let delegate = windowScene.delegate as? SceneDelegate else { return nil }
return delegate
}
}
And if you're in need of an extension to reach the UIWindow from a ViewController with iOS12 and iOS13 Support:
extension UIViewController {
var window: UIWindow? {
if #available(iOS 13, *) {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let delegate = windowScene.delegate as? SceneDelegate, let window = delegate.window else { return nil }
return window
}
guard let delegate = UIApplication.shared.delegate as? AppDelegate, let window = delegate.window else { return nil }
return window
}
}
If you want to use ScenceDelegate. In scene(_:willConnectTo:options:, creates a new UIWindow, sets the window’s rootViewController and makes this window the key window.
If you don't want to use ScenceDelegate, you can try to remove it by following this.

Resources