How to load specific storyboard depending on device in Objective C?

374 Views Asked by At

This is a repost since the other one was closed.

I have trouble with auto layout, so I would just prefer to make two storyboards, iPad and iPhone. All I want is to detect the type of device it is or the size and then display their respected storyboard. I have tried just about every solution I have found on StackOverflow and I cannot get it to work.

Currently, I detect the size of the device on the AppDelegate.m under DidFinishLaunchingWithOptions then load the storyboard and set the initialViewController. When I run the iPad simulator it runs and displays correctly, and in the console it returns the correct storyboard and view controller. However, when I run the iPhone simulator it displays the iPad storyboard but in the console, it shows that it returned the iPhone storyboard and the correct initialviewcontroller.

Also, I am new to Objective-C but getting the hang of it. Thanks, hope someone can help. Here is my App Delegate code.

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // Override point for customization after application launch.
    UIStoryboard *storyboard = self.window.rootViewController.storyboard;
    UIViewController *rootViewController;
    
    // detect screen height
    int height = [UIScreen mainScreen].fixedCoordinateSpace.bounds.size.height;
    NSLog(@"The fixed height is %i", height);
    
    // determine if this is an iPad
    if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
        
        // it's an iPad
        if (height >= 1024) {
            
            storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
            rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"loginViewController"];
            
            NSLog(@"LOADING MAIN/IPAD STORYBOARD");
        }
        
    } else {
        // it's an iPhone
        storyboard = [UIStoryboard storyboardWithName:@"iPhone" bundle:nil];
        rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"iPhoneLoginViewController"];
        
        NSLog(@"LOADING IPHONE STORYBOARD");
    }
    
    NSLog(@"Root View Controller: %@", rootViewController);
    NSLog(@"Storyboard: %@", storyboard);
    
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
    
    return YES;
}
#pragma mark - UISceneSession lifecycle


- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}


- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

@end   

Here is my Info.plist:

Info.plist Property List

    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UIMainStoryboardFile~ipad</key>
    <string>Main</string>
    <key>UIMainStoryboardFile~iphone</key>
    <string>iPhone</string>
    <key>UIRequiredDeviceCapabilities</key>

Below are screenshots of iPad VS iPhone Results:

iPad Simulator with its correct storyboard

iPhone Simulator showing incorrect storyboard

iPhone Storyboard

1

There are 1 best solutions below

3
matt On

You don't have to detect anything. The Info.plist itself will arrange for the runtime to load a different storyboard depending on whether this is an iPad or not. There's a simple naming convention that governs this behavior: just make another key in the Info.plist ending in ~ipad.

So, if you want to have two different main storyboards, use the Info.plist naming convention: configure two "Main storyboard file base name" keys, UIMainStoryboardFile and UIMainStoryboardFile~ipad — or, with window scenes under iOS 13 and later, configure two "Application Scene Manifest" keys, UIApplicationSceneManifest and UIApplicationSceneManifest~ipad, that specify different UISceneStoryboardFile values.