AppDelegate not used when scenes configured in Info.plist

1k views Asked by At

I have an old (Objective-C) iOS app that I expanded to Mac Catalyst, and now I want to add multi-window support to the Mac version, without affecting the iOS version. In accordance with several tutorials (example), I've set up a SceneDelegate like this...

@implementation SceneDelegate

#if TARGET_OS_MACCATALYST

@synthesize window;

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    if ([scene isKindOfClass:[UIWindowScene class]]) {
        self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
        self.window.rootViewController = [[MainView alloc] init];
        [self.window makeKeyAndVisible];
    }
}

@end

#endif

...added this to AppDelegate...

#if TARGET_OS_MACCATALYST

- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(nonnull UISceneSession *)connectingSceneSession options:(nonnull UISceneConnectionOptions *)options {
    return [[UISceneConfiguration alloc] initWithName:@"Main" sessionRole:connectingSceneSession.role];
}

#endif

...and added this to Info.plist:

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
</dict>
<key>UIApplicationSceneManifest-macos</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <true/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>Main</string>
                <key>UISceneClassName</key>
                <string>UIWindowScene</string>
                <key>UISceneDelegateClassName</key>
                <string>SceneDelegate</string>
            </dict>
        </array>
    </dict>
</dict>

I'm still doing a lot of setup in the AppDelegate's application:didFinishLaunchingWithOptions: method, but that method was never called, nor was application:configurationForConnectingSceneSession:options:, and there were no errors in the console. So I moved the definition of the scene from the Info.plist file to the application:configurationForConnectingSceneSession:options: method, like this...

- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(nonnull UISceneSession *)connectingSceneSession options:(nonnull UISceneConnectionOptions *)options {
    UISceneConfiguration *config = [[UISceneConfiguration alloc] initWithName:@"Main" sessionRole:UIWindowSceneSessionRoleApplication];
    config.sceneClass = [UIWindowScene class];
    config.delegateClass = [SceneDelegate class];
    return config;
}

...leaving only this in Info.plist:

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
</dict>
<key>UIApplicationSceneManifest-macos</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <true/>
</dict>

Now it works as expected.

Is defining the scene configurations in Info.plist supposed to completely bypass the AppDelegate? Based on the documentation, it seems like maybe that's supposed to bypass application:configurationForConnectingSceneSession:options:, but I haven't seen any indication that it should also bypass application:didFinishLaunchingWithOptions:. Some tutorials explicitly say that method should still run.

I tried removing the application:configurationForConnectingSceneSession:options: method in case defining the configurations in two places was confusing the SDK, but application:didFinishLaunchingWithOptions: was still not called, as long as UISceneConfigurations was in Info.plist.

I can tell whether application:didFinishLaunchingWithOptions: is called or not by adding a breakpoint to its first line. The breakpoint gets hit unless I add the UISceneConfigurations dictionary to the Info.plist, but making only that change causes the breakpoint to not get hit.

0

There are 0 answers