Separate Storyboard for iPhone and iPad With Multiple Windows

Hello,


I have an application in which I want to use a separate storyboards for iPhone and iPad. I have this specified in Info.plist. I also now want to support iOS/iPadOS 13's multiple window feature.


In order to setup multiple windows in Info.plist I have to specify a storyboard within "Application Scene Manifest". As you might expect, this now overrides my previously specified iPhone/iPad storyboard setting.


Is it possible to continue using separate iPhone and iPad storyboards while still supporting multiple windows on the iPad/Mac (Catalyst) version?


One way I could see overcoming this would be to create a separate target for iPhone and migrate all iPhone related data to that target however that would be quite an involved process that I would like to avoid if possible.


Thanks



Here is my Info.plist for reference:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>$(DEVELOPMENT_LANGUAGE)</string>
  <key>CFBundleExecutable</key>
  <string>$(EXECUTABLE_NAME)</string>
  <key>CFBundleIdentifier</key>
  <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>$(PRODUCT_NAME)</string>
  <key>CFBundlePackageType</key>
  <string>APPL</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleVersion</key>
  <string>$(CURRENT_PROJECT_VERSION)</string>
  <key>LSApplicationCategoryType</key>
  <string>public.app-category.education</string>
  <key>LSRequiresIPhoneOS</key>
  <true/>
  <key>UIApplicationSceneManifest</key>
  <dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
  <key>UIWindowSceneSessionRoleApplication</key>
  <array>
  <dict>
  <key>UISceneClassName</key>
  <string></string>
  <key>UISceneConfigurationName</key>
  <string>Default Configuration</string>
  <key>UISceneDelegateClassName</key>
  <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
  <key>UISceneStoryboardFile</key>
  <string>MainiPad</string>
  </dict>
  </array>
  </dict>
  </dict>
  <key>UIBackgroundModes</key>
  <array>
  <string>audio</string>
  </array>
  <key>UILaunchStoryboardName</key>
  <string>LaunchScreen</string>
  <key>UIMainStoryboardFile~ipad</key>
  <string>MainiPad</string>
  <key>UIMainStoryboardFile~iphone</key>
  <string>MainiPhone</string>
  <key>UIRequiredDeviceCapabilities</key>
  <array>
  <string>armv7</string>
  </array>
  <key>UISupportedInterfaceOrientations~ipad</key>
  <array>
  <string>UIInterfaceOrientationPortrait</string>
  <string>UIInterfaceOrientationPortraitUpsideDown</string>
  <string>UIInterfaceOrientationLandscapeLeft</string>
  <string>UIInterfaceOrientationLandscapeRight</string>
  </array>
  <key>UISupportedInterfaceOrientations~iphone</key>
  <array>
  <string>UIInterfaceOrientationPortrait</string>
  </array>
</dict>
</plist>
Answered by devjun in 409565022

hi zmclearan,

I was searching and found your post. I have the same problem with you but i think i've solved this.

You don't need to specify the Storyboard name in your UIApplicationSceneManifest section in the info.plist file. You can leave the UISceneConfigurations in UIApplicationSceneManifest section empty and specify a storyboard at runtime in the UIApplicationDelegate method. Just like this:


UIApplicationSceneManifest
  
  UIApplicationSupportsMultipleScenes
  
  UISceneConfigurations
 

And in your UIApplicationDelegate:

@available(iOS 13.0, *)
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
       
        let config = UISceneConfiguration(name: "Default Configuration", sessionRole: .windowApplication)
        config.sceneClass = UIWindowScene.self
        config.delegateClass = SceneDelegate.self
        if UIDevice.current.userInterfaceIdiom == .phone {
            config.storyboard = UIStoryboard(name: "Main", bundle: nil)
        } else {
            config.storyboard = UIStoryboard(name: "Main_ipad", bundle: nil)
        }
       
        return config
    }
Accepted Answer

hi zmclearan,

I was searching and found your post. I have the same problem with you but i think i've solved this.

You don't need to specify the Storyboard name in your UIApplicationSceneManifest section in the info.plist file. You can leave the UISceneConfigurations in UIApplicationSceneManifest section empty and specify a storyboard at runtime in the UIApplicationDelegate method. Just like this:


UIApplicationSceneManifest
  
  UIApplicationSupportsMultipleScenes
  
  UISceneConfigurations
 

And in your UIApplicationDelegate:

@available(iOS 13.0, *)
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
       
        let config = UISceneConfiguration(name: "Default Configuration", sessionRole: .windowApplication)
        config.sceneClass = UIWindowScene.self
        config.delegateClass = SceneDelegate.self
        if UIDevice.current.userInterfaceIdiom == .phone {
            config.storyboard = UIStoryboard(name: "Main", bundle: nil)
        } else {
            config.storyboard = UIStoryboard(name: "Main_ipad", bundle: nil)
        }
       
        return config
    }

I cannot begin to thank you! This worked perfectly! It was so simple, I do not know why I didn't think of it. It throws a few errors in the console however the applicaiton works perfectly. It's like I can have my cake and eat it too...

Hi,
i've the same problem, i've modified the connectingSceneSession functions in AppDelegate, but it is never called

If your connectingSceneSession is not called, check your app Info.plist:

  • UIApplicationSupportsMultipleScenes = true (YES)
  • UISceneConfigurations : empty dictionary (array)
<key>UIApplicationSceneManifest</key>
	<dict>
		<key>UIApplicationSupportsMultipleScenes</key>
		<true/>
		<key>UISceneConfigurations</key>
		<dict/>
	</dict>
Separate Storyboard for iPhone and iPad With Multiple Windows
 
 
Q