A while ago I’ve written an article about how to load different storyboards depending on the screen size of an iOS device. Back in those days (2013) it was all a bit simpler than it is today, and I looked into it mainly because I loathed Auto Layout so much.
I felt it was time for an update, so here it is!
Things haven’t gotten any easier in iOS, because currently we have the following 5 screen sizes to deal with:
- iPhone 6 Plus: 736×414 @3x
- iPhone 6: 667×375 @3x
- iPhone 5s: 568×320 @2x
- iPhone 4s: 480×320 @2x
- all iPads: 1024×768 @1x / @2x
It’s very difficult to make a UI look nice on all devices with a single UIStoryboard, and in the above video I’m showing you an alternative: design a completely different storyboard for each screen size.
The upkeep of such an app will be a little more complex, but it puts us in full control of the user experience, and not some compromise that sounds good in the Apple presentation (and sucks in reality).
In principle, the following steps are involved:
- design various storyboards
- detect the current device’s screen height
- load the appropriate storyboard
- make it “key and visible”
Detecting the screen size
If your app is set to “auto-rotate” (i.e. both portrait and landscape modes, or portrait only), the screen height will detect the longer side of the screen. This is true even if the app is started in landscape mode. Determining screen height can be done like this:
1 2 |
int screenHeight = [UIScreen mainScreen].bounds.size.height; NSLog(@"Screen Height is %i", screenHeight); |
Note that if you set your app to “landscape only” mode, the height parameter will return the shorter side of the screen – in which case, bounds.size.width to determine the longer portion of the screen. Thanks to Johan Grip for bringing this to my attention!
iOS 7 compatibility
Note that the screen size is orientation dependant since iOS 8 – previous versions did not take this into a account. If you must support iOS 7 and earlier it gets a lot more complicated (and I won’t cover this here – sorry).
However, this Stack Overflow discussion may help you in that case: http://stackoverflow.com/questions/24150359/is-uiscreen-mainscreen-bounds-size-becoming-orientation-dependent-in-ios8
Loading the correct UIStoryboard
With this handy integer in place, we can build a switch statement to react according to the screen height. I’m using the following method that returns my desired storyboard in my AppDelegate implementation file.
If you’re not worried about each single size, feel free to write a shorter if/then/else type method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
- (UIStoryboard *)grabStoryboard { // determine screen size int screenHeight = [UIScreen mainScreen].bounds.size.height; UIStoryboard *storyboard; switch (screenHeight) { // iPhone 4s case 480: storyboard = [UIStoryboard storyboardWithName:@"Main-4s" bundle:nil]; break; // iPhone 5s case 568: storyboard = [UIStoryboard storyboardWithName:@"Main-5s" bundle:nil]; break; // iPhone 6 case 667: storyboard = [UIStoryboard storyboardWithName:@"Main-6" bundle:nil]; break; // iPhone 6 Plus case 736: storyboard = [UIStoryboard storyboardWithName:@"Main-6-Plus" bundle:nil]; break; default: // it's an iPad storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; break; } return storyboard; } |
Displaying the storyboard
Inside our AppDelegate method didFinishLaunchingWithOptions, we’ll call the above method and grab the storyboard we need. To make it show up, we need to load it as the window’s root view controller and declare it “key and visible”. This is akin to the old-style way of making things appear on our iOS screens.
1 2 3 4 5 6 7 8 9 10 11 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // grab correct storyboard depending on screen height UIStoryboard *storyboard = [self grabStoryboard]; // display storyboard self.window.rootViewController = [storyboard instantiateInitialViewController]; [self.window makeKeyAndVisible]; return YES; } |
Note that using this approach will override whatever storyboard is declared in your target (under General – Deployment Info – Main Interface).
Demo Project
I’ve updated this project on GitHub, it shows exactly what I’m building in the screencast. Play and enjoy 🙂
Podcast: Download (Duration: 19:26 — 17.8MB)
Watch the full course in one convenient playlist:

