How to Update Your Apps for the 4-Inch iPhone 5 Display

The iPhone 5 comes with a gorgeous new screen that has a lot more space for your app’s content. But like in the past with the Retina display, you need to do a little work to gain the benefits of the larger screen. With a little thought and design, your apps can make use of the added space in interesting ways. By .

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

The Incredible Expanding and Contracting Diner

Now you need to expand the diner itself – that is, the background and counter images.

Switch back to the smaller screen size and select both the background and counter views: Image View – bg_wall.png and Image View – bg_counter.png, respectively. They already have leading constraints, so if you pin the trailing side, these views will stretch when the screen expands. Again, choose the pin icon…

Add the Trailing Space to Superview constraint…

And then hit the form factor toggle button to see the effect.

The background tries to expand as you expected, but the image isn’t large enough, so it just gets centered. You need to change the image when the app runs on a 4-inch screen. But there isn’t a mechanism to say, “Use this image for a 3.5-inch screen and this other image for a 4-inch screen,” so this is where you need to do a little coding.

In the storyboard, turn on the assistant view and control-drag the counter and background UIViews to create IBOutlets. Name them ibCounter and ibBackgroundImage.

Next select iOSDiner-Prefix.pch in the Supporting Files folder and add this line right before the last #endif at the bottom of the file (credit to StackOverflow):

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)

This will let you know whether or not you are running on a bigger screen. It just subtracts the size of an iPhone 5 screen, in points, from the size of the current device’s screen. If the answer is zero, then you know the device is an iPhone 5.

Using this macro, in IODViewController.m, add the following code to the end of viewWillAppear::

if (IS_IPHONE5) {
    self.ibBackgroundImage.image = [UIImage imageNamed:@"bg_wall-568h.png"];
    self.ibCounter.image = [UIImage imageNamed:@"bg_counter-568h.png"];
}

This code block checks to see if it is running on an iPhone 5 (large screen); if it is, it sets the images to the newer, larger versions. These images are already part of the starter project you downloaded.

You might be asking, “Hey, shouldn’t it be bg_wall–568h@2x.png?” Well, no. Remember UIImage automatically appends “@2x” to look for retina images. So even though you only included the bg_wall–568h@2x.png image, you select the image without the “@2x” appended at the end.

Build and run the app, and it should look like this:

Move Over, You’re Crowding Me!

Now there is a larger background for the app, but also a lot of unused space on the right side. Meanwhile, everything crammed together on the left side makes it awkward for Bill, the cashier, to do his job. You’re going to reposition him to use the extra space.

Once again, make sure you are editing the storyboard using the 3.5-inch form factor. Now select Bill (the view named Image View – person.png) and add a new Trailing Space to SuperView pin constraint.

Just as with the Next arrow, Bill already has a Leading constraint, so if you switch to the 4-inch screen now, Bill will be stretched. You know Bill works at a fast food restaurant but he hasn’t gained that much weight! Select the Leading Space to: Image View constraint and delete it.

Toggle the form factor switch again.

Great! Bill is now pinned to the right and moves into place on the larger screen.

Note: The item description area (it says “Hamburger” in the screenshot above) is also pinned to the right. But you didn’t change this. So what happened?

It’s because that image is pinned to the text label, which is pinned to the Bill image. So when Bill’s position is changed, the changes cascade down and update the description label and description image. Cool, huh?

Note: The item description area (it says “Hamburger” in the screenshot above) is also pinned to the right. But you didn’t change this. So what happened?

It’s because that image is pinned to the text label, which is pinned to the Bill image. So when Bill’s position is changed, the changes cascade down and update the description label and description image. Cool, huh?

Wait… Doesn’t Auto Layout Require iOS 6?

If you try running iOS Diner app right now in the iPhone 5.1 Simulator, it will crash on start-up. In fact, had you tried it, this would have happened right after you enabled Auto Layout on the storyboard. That’s because Auto Layout strictly requires iOS 6.

This may not be a big deal for your app, because at this time roughly 87% or so of users are using iOS 6, but it is something to keep in mind.

When you release an app, you have to decide the minimum version of iOS you will support. For newer apps, you may wish to choose iOS 6, but in this tutorial you’re upgrading an existing app. That adds the additional wrinkle that if you raise the minimum iOS version, your current users may not be able to upgrade to your latest software.

Basically, you have two choices:

  1. You can change the project’s deployment target, requiring the device to have that version of iOS for your app to run.
  2. You can make your app backwards-compatible.

Let’s go over both options. You can do either one, or both for this tutorial – or skip this entire section if you would prefer!

Changing the deployment target

To change the deployment target, simply select the iOSDiner project in the Project Navigator and then select iOSDiner at the top, under Projects. Choose the Info tab and change the iOS Deployment Target to 6.0 (at least).

Note that you can also change this setting directly on the iOSDiner build target in the Targets list, as shown below.

The difference between the two approaches is that the value in the specific build target overrides the value set in the project. This is useful if you have multiple build targets that need to deploy on different platforms.

Making the app backwards compatible

If you’d prefer to make your app backwards-compatible with earlier versions of iOS, then you’ll have to do a bit more work. If you’re using Storyboards, as in IOSDiner, then the easiest way to accomplish it is to create two different Storyboards, one that uses Auto Layout and one that does not. Then you’ll tell your app which to use when it starts up.

Right now the app is set to load a storyboard on launch. This is referred to by the project as its Main Storyboard.

For this dual storyboard approach, you need to stop the app from auto-loading a storyboard at launch. To do so, simply clear out the Main Storyboard field in the target’s Summary settings. Just remove the current value so it looks like the following screenshot:

Select MainStoryboard.storyboard and choose File\Duplicate…. Name your new file MainStoryboard-legacy.storyboard and save it.

Now select MainStoryboard-legacy.storyboard, set your editor to display the smaller form factor and uncheck Use Autolayout.

Now open IODAppDelegate.m and make the following changes from this article.

Add the following code just above the @implementation IODAppDelegate:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending)

This defines a macro that lets you check the version of iOS on a device against some minimum version that you specify when calling it.

Replace application:didFinishLaunchingWithOptions: with the following:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // 1
  UIStoryboard *mainStoryboard = nil;
  if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
    mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
  } else {
    mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard-legacy" bundle:nil];
  }
  
  // 2
  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  self.window.rootViewController = [mainStoryboard instantiateInitialViewController];
  [self.window makeKeyAndVisible];
  
  return YES;
}

Here’s what happening above:

  1. This checks the version of iOS running on the device. If it is at least 6.0, it loads the storyboard you worked on earlier with Auto Layout enabled. Otherwise, it loads the other storyboard that does not use Auto Layout.
  2. This sets up the app’s window with a view controller created from the appropriate storyboard.

Now you have two good options for how to deal with Auto Layout and device compatibility – but there’s one big question that remains.