Issue:
I find some unexpected behavior regarding the AppDelegate method application(_:configurationForConnecting:options:)
.
The documentation states:
UIKit calls this method shortly before creating a new scene.
I would expect that this is the case every time the app is launched.
The method is indeed called when I launch my app for the first time, however for all subsequent launches, it is not.
Reproduce:
I have a very simple test case to reproduce:
AppDelegate
like so:
// from Apple's sample project:
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.
print("I was called!"). // <--- debugging statement
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
Question:
Why is application(_:configurationForConnecting:options:)
not being called on second launch?
(Is it expected behavior, if yes why / Is it a bug by Apple)
This seems to be expected behaviour, and makes sense once you understand what's going on, but it's not documented. I've just spent some fairly traumatic time getting to the bottom of it. Oh, Apple.
The key thing to know is that when you relaunch an app, the windows from the previous run are restored.
(It also helps to remember that an app can have multiple types of window – each represented by a scene configuration – which is why you might implement this delegate method in the first place.)
Case 1: App launched for the first time ever
The app doesn't know what type of scene to put in the window, and calls application(_:configurationForConnecting:options:)
to find out. So far things are as we expect. (If you don't implement this delegate method, it just falls back to the first suitable entry in your Info.plist
's scene manifest, if it has one.)
Case 2: New window created (for apps that support multiple windows)
(e.g. by dragging the dock icon on iPad). The app doesn't know what to put in this window either. Same as case 1.
Case 3: App relaunched
The OS wants to restore your windows. To do this, it has remembered the scene configs of the windows you had open last time. Surprise! It knows what scenes to put in the windows, and doesn't ask your app delegate. It just goes ahead and creates the scenes using the remembered configs.
For the poor developer thinking in terms of a window being created when the app starts up, this is confusing. But if you think in terms of windows being restored at startup, not created - even when there is only one - it starts to make sense.
Now, if you want to reset things so your windows are forgotten and your delegate method is called on next launch:
Note 1: In Catalyst, it seems that only the first window is restored on relaunch, but otherwise behaviour is the same as above. Have now observed this not to be true. Perhaps it's inconsistent.
Note 2: You can also restore your windows' content, not just their type, using UIWindowSceneDelegate
and UISceneSession.stateRestorationActivity
, but that's another story.
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