Interesting. I never noticed that SceneDelegate.swift file before. It’s been a several years since I messed with UIKit programming and that looks like something new. Checking the Apple docs, I see that the UIScene and UIWindowSceneDelegate stuff were added new in iOS 13. I’ll have to wrap my mind around what these new changes mean.
At first blush, it looks like a lot of the functions that used to be in AppDelegate like the “willEnterForeground” and “didEnterBackground” stuff were stripped out of there and relocated to the SceneDelegate file. Along with some other changes as well.
Thanks for sharing that, @ibex10. What you have shown is quite interesting. You can’t reach the view’s superview or UIWindow from the ViewController’s viewDidLoad method, but you can reach them through the SceneDelegate’s sceneDidBecomeActive method. That makes me curious about the changes made involving SceneDelegate over the last several years.
I also noticed that AppDelegate no longer has a reference to the UIWindow, but SceneDelgate now has it. That’s an interesting change to UIKit that’s happened in recent years.
After some experimenting, I found that a view controller’s viewDidAppear method is a better place than viewDidLoad for making calls to the view’s superview or window. Apparently, by the time iOS calls viewDidAppear your app will have configured the view hierarchy more fully than when viewDidLoad is called.
Try making a new Xcode project from the iOS “App” template (I’m using Xcode 12.5) and paste the following into your ViewController class:
override func viewDidAppear(_ animated: Bool) {
print("Window is: \(self.view.window)")
print("Superview is: \(self.view.superview)")
print("Reach window by chaining calls to superview: \(self.view.superview?.superview?.superview)")
}
All three of these calls worked for me. Note that you may have to go a LOT deeper with the chained superview calls before you reach the window in a more complex project. It’s probably better to just use self.view.window
if you want to reach the window.
In conclusion, I was able to confirm that the book’s explanation is accurate. It explains that UIWindow is the ultimate superview of the ViewController’s UIView, which is correct.
My confusion was about how to reach the UIWindow through code from the view controller. Turns out my mistake was trying to reach it too early in the view’s lifecycle. I should have tried to access it from viewDidAppear rather than in viewDidLoad. Thanks ibex10 for your help!