6

I'm new to the SceneDelegate setup. I notice that in info.plist, we have a mapping under Scene Configuration:

Configuration Name: Default Configuration <- this key
Delegate Class Name: $(PRODUCT_MODULE_NAME).SceneDelegate <- this file

Then in AppDelegate's connectingSceneSession, we return the config with the key Default Configuration.

return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)

Is it possible to avoid this (key -> file) mapping in info.plist, and hook it up programmatically?

Note: I am not asking about storyboard. There are tons of tutorials about removing storyboard and I know that.

  • Why are you trying to do this? Here's my take on SceneDelegate - hopefully it'll help. Nearly two years ago it was introduced along side of a "Supports Multiple Windows" checkbox for your project. While it makes little sense on an iPhone, on an iPad (that offers split screen natively) it does. Now, there's a few ways to "opt out" of using SceneDelegate - see this question: https://stackoverflow.com/questions/57467003/opt-out-of-uiscenedelegate-swiftui-on-ios/57467262#57467262 - but again, why mess with info.plist? –  Mar 21 '21 at 09:17
  • 1
    @dfd because i prefer pure code over info.plist setup. One example, in code it's less likely to make mistakes like typo in "Default Configuration". –  Mar 21 '21 at 18:35
  • 1
    I'm like you more or less - I prefer code over storyboards or xib. There's nothing you can do in either of them that you cannot in code. But info.plist? Never thought about it. I let Xcode do what Apple thinks it should I guess. The link above is my most upvoted answer - and it BY FAR the second best upvoted answer. Go figure. I'll have to check my old projects (many that target iOS 9+) to see what is in info.plist, as all of them *do not* have a scene delegate. –  Mar 22 '21 at 01:21
  • @dfd thanks for the link. But i think i still prefer to keep scene delegate for potential future use case. –  Mar 22 '21 at 06:41

1 Answers1

8

Remove "Scene Configuration" (UISceneConfigurations) entry from Info.plist, and instantiate UISceneConfiguration in AppDelegate:

// class AppDelegate
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    if connectingSceneSession.role == UISceneSession.Role.windowApplication {
        let config = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
        config.delegateClass = SceneDelegate.self
        config.storyboard = UIStoryboard(name: "Main", bundle: nil)
        return config
    }
    fatalError("Unhandled scene role \(connectingSceneSession.role)")
}

From the manual:

Implement this method if you do not include scene-configuration data in your app's Info.plist file, or if you want to alter the scene configuration data dynamically. UIKit calls this method shortly before creating a new scene.

paiv
  • 5,491
  • 22
  • 30
  • 1
    When running on iOS 15 I had to delete the app and reinstall in order for this function to be called for windowApplication role. It acted like the OS was caching the Info.plist UISceneConfigurations values. – sfaxon Jul 13 '22 at 13:45
  • @paiv: I have referred to your answer on how to set the SceneDelegate via code. In my case, if I use 'extension' in Swift, to extend SceneDelegate to break the implementation to 2 files, the methods inside extension does not get called. I have posted the question here : https://stackoverflow.com/questions/74389631/interfaces-of-swift-extension-not-called-if-put-in-separate-target – Abhi_M Nov 15 '22 at 13:27