I need to support iOS 12 and iOS 13.
Should I be duplicating code between AppDelegate
and SceneDelegate
?
For example:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
}
and
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
return true
}
If I don't do this, in 1 version I end up with a black screen, but if I do and print in the viewDidLoad
method of HomeViewController
I can see it is called twice.
I update my didFinishLaunchingWithOptions
and I can see in iOS13
it is still called twice.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
guard #available(iOS 12, *) else { return true }
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
return true
}
AppDelegate is responsible for handling application-level events, like app launch and the SceneDelegate is responsible for scene lifecycle events like scene creation, destruction and state restoration of a UISceneSession.
Overview. Your app delegate object manages your app's shared behaviors. The app delegate is effectively the root object of your app, and it works in conjunction with UIApplication to manage some interactions with the system.
The Delegate Pattern in Swift In Swift, a delegate is a controller object with a defined interface that can be used to control or modify the behavior of another object. One example is the UIApplicaitonDelegate in an iOS app.
Use your UISceneDelegate object to manage life-cycle events in one instance of your app's user interface. This interface defines methods for responding to state transitions that affect the scene, including when the scene enters the foreground and becomes active, and when it enters the background.
You do need to duplicate the code but you need to make sure it runs only on the correct system. In iOS 13 you don’t want that application delegate didFinishLaunching
body code to run, so use an availability check to prevent it.
In the same way, use availability to hide the window scene stuff from iOS 12.
Here's the basic sketch of a solution that runs correctly on both iOS 12 and iOS 13:
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 vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
self.window!.backgroundColor = .red
}
return true
}
}
import UIKit
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window : UIWindow?
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
self.window!.backgroundColor = .red
}
}
}
import UIKit
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("view did load")
self.view.backgroundColor = .green
}
}
Note that dealing with other duplicates, such as the application activating, is much simpler because if you support window scenes the application delegate method won't be called on iOS 12. So the problem is confined to this one situation, namely where you have window / root view controller manipulations to perform at launch (e.g. no storyboard).
Xcode 11.* and Swift 5.*
Follow the steps given below after that your code will work fine for both iOS 12 and iOS 13 -
Hope this will work for someone. Happy Coding 🤓
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With