So, you're being a good modern iOS developer and adopting scene support in your UIKit app. You've implemented application(_:configurationForConnecting:options:), but it's not being called consistently. What's going on? Is it a bug in iOS?

In fact, things are probably behaving as they should, but this isn't well documented and can be super confusing. Even once I started to realise what was going on, it took quite some time to get to the bottom of it all.

It's all to do with scene restoration.

What happens when your app starts

When your app starts up after a previous launch, iOS wants to restore its windows so the user feels like they're picking up where they left off. To do this, iOS saved the configuration details of each of your app's scenes last time the app was run. When the app is launched again, it reads the saved scene config and recreates those scenes.

This happens even on the iPhone, where you only have one window.

Here are the various permutations at launch time, assuming you've implemented application(_:configurationForConnecting:options:) for some custom behaviour:

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

An iPad user creates a new window. The app doesn't know what to put in this window either. This is the 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.

How to forget saved windows

During development, you might want to reset things so your windows are forgotten and your delegate method is called on next launch. To do that:

  • for iOS, delete the app
  • for Catalyst, delete the app's container

Restoring content

This is all about restoring scene types. To be most useful to the user you might want to restore windows' content as well. Your starting point for this is NSUserActivity and the various state methods on your UIWindowSceneDelegate. Good luck.