Migrating iPhone 3.x apps to iPad and iOS 4.0

Right now, creating Universal Applications for the iPod touch, the iPhone and the iPad is not really a straightforward task. The current panorama of iOS-compatible software and hardware platforms is getting more and more complex, and this blog post is a small guide (by no means exhaustive) of tips and tricks that have helped me get my apps running in as many platforms as possible, with as few headaches as possible.

First of all, a few warnings:

Panorama

Waiting for an unification of the iPad and the iOS 4 frameworks (probably later this year), the current panorama of software and hardware iOS platforms looks as follows:

iPhoneiPod touchiPad
3G3GS42nd gen3rd gen
iPhone OS 3.1xxxx
iPhone OS 3.2x
iOS 4.0(ls)x(ls)x
Year Released200820092010200820092010
RAM (MB)128256512128256256
CPU (MHz)6208331 GHz6208331 GHz

(ls): limited support, particularly for multitasking.

For practical purposes, I’ve omitted in the table above the fact that the iPhone 3G is (theoretically) able to run iOS 4. Something that has been empirically proved to be a bad idea.

Upgrading Xcode Projects to iOS 4

Your Xcode 3.1 iPhone project can be migrated to iOS 4 as follows:

Old Entitlements.plist:

<plist version="1.0">
<dict>
    <key>get-task-allow</key>
    <false></false>
</dict>
</plist>

New Entitlements.plist:

<plist version="1.0">
<dict>
    <key>application-identifier</key>
    <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
    <key>keychain-access-groups</key>
    <array>
        <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
    </array>
</dict>
</plist>

After doing the steps above, you should have an application running on iPhone OS 3.1, 3.2 (as an iPhone application) and 4.0, offering exactly the same functionality and ready to be sent to the App Store.

Create a Universal iPhone and iPad application

Creating an iPad-compatible application from your iPhone app requires much more than just adapting your source code; the user experience of iPad apps is a completely different beast than that of iPhone apps, so I strongly recommend you ask a graphic and/or UX designer for help. I can’t stress this too much; iPad apps aren’t just “big” iPhone apps. They are much, much more.

Technically speaking, in the simplest of terms, you should be able to migrate most UIKit-based application following the standard path provided by Apple:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
        NSLog(@"iPad Idiom");
    else
#else
        NSLog(@"iPhone Idiom");
#endif

Testing your code in different devices

My advice is the following: don’t upgrade your old iPhone to iOS 4, particularly if you own a 3G. Keep it running under 3.1 and get the new iPhone 4 as soon as you can. This has two major advantages:

In my personal situation, I have my old iPhone 3G running iPhone OS 3.1.3, and a second generation iPod touch running iOS 4. And of course, my iPad runs iPhone OS 3.2.1.

Adapting your code for different platforms

Although Apple recommends using the UI_USER_INTERFACE_IDIOM macro, sometimes you need a tighter control in your code. For this, I have used three different techniques:

- (void)showAdvertising
{
    Class klass = NSClassFromString(@"ADBannerView");
    if (klass)
    {
        ADBannerView *adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0.0, 416.0, 320.0, 50.0)];
        adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifier320x50;
        adView.delegate = self;
        [self.view addSubview:adView];
    }
}

Finally, MPMoviePlayerController requires special attention, because it’s widely used in many applications and also because it has been greatly improved (and changed) between iPhone OS 3.1, iPhone OS 3.2 and iOS 4. Those changes include, in some cases, deprecated APIs, so here I’ll just link to this excellent article by John Muchow in the iPhone Developer Tips blog, which explains all the problems and the possible solutions.

Conclusion

As you could see, creating universal apps is not easy, but it isn’t impossible either; it requires a bit of attention and lots of testing. Do you have any tips or links that you would like to share? Feel free to add more information in the comments below.