The process for creating an iPad application depends on whether you are creating a new application or porting an existing iPhone application. If you are creating a new application, you can use the Xcode templates to get started. However, because it runs iOS, it is possible to port existing iPhone applications so that they run natively on an iPad, and not in compatibility mode. Porting an existing application requires making some modifications to your code and resources to support iPad devices, but with well-factored applications, the work should be relatively straightforward. Xcode also makes the porting process easier by automating much of the setup process for your projects.
If you do decide to port an existing iPhone application, you should consider both how you want to deliver the resulting applications and what is the best development process for you. The following table lists the possible porting approaches and what each one involves.
Create a universal application that is optimized for all device types.
Use a single Xcode project to create two separate applications: one for iPhone and iPod touch devices and one for iPad devices.
Use separate Xcode projects to create applications for each type of device.
Apple highly recommends creating a universal application or a single Xcode project. Both techniques enable you to reuse code from your existing iPhone application. Creating a universal application allows you to sell one application that supports all device types, which is a much simpler experience for users. Of course, creating two separate applications might require less development and testing time than a universal application.
A universal application is a single application that runs optimized for iPhone, iPod touch, and iPad devices. Creating such a binary simplifies the user experience considerably by guaranteeing that your application can run on any device the user owns. Creating such a binary does involve a little more work on your part though. Even a well-factored application requires some work to run cleanly on both types of devices.
The following sections highlight the key changes you must make to an existing application to ensure that it runs natively on any type of device.
The first step to creating a universal application is to configure your Xcode project. If you are creating a new project, you can create a universal application using the Window-based application template. If you are updating an existing project, you can use Xcode’s Upgrade Current Target for iPad command to update your project:
Open your Xcode project.
In the Targets section, select the target you want to update to a universal application.
Select Project > Upgrade Current Target for iPad and follow the prompts to create one universal application.
Xcode updates your project by modifying several build settings to support both iPhone and iPad.
Important: You should always use the Upgrade Current Target for iPad command to migrate existing projects. Do not try to migrate files manually.
The main change that is made to your project is to set the Targeted Device Family build setting to iPhone/Pad. The Base SDK of your project is also typically changed to iPhone Device 3.2 if that is not already the case. (You must develop with the 3.2 SDK to target iPad.) The deployment target of your project should remain unchanged and should be an earlier version of the SDK (such as 3.1.3) so that your application can run on iPhone and iPod touch devices.
In addition to updating your build settings, Xcode also creates a new main nib file to support iPad. Only the main nib file is transitioned. You must create new nib files for your application’s existing view controllers. Your application’s Info.plist
is also updated to support the loading of the new main nib file when running on iPad.
When running on iOS 3.1.3 or earlier, your application must not use symbols introduced in iOS 3.2. For example, an application trying to use the UISplitViewController
class while running in iOS 3.1 would crash because the symbol would not be available. To avoid this problem, your code must perform runtime checks to see if a particular symbol is available before using it. For information about how to perform the needed runtime checks, see “Adding Runtime Checks for Newer Symbols.”
Most of the existing keys in your Info.plist
should remain the same to ensure that your application behaves properly on iPhone and iPod touch devices. However, you should add the UISupportedInterfaceOrientations
key to your Info.plist
to support iPad devices. Depending on the features of your application, you might also want to add other new keys introduced in iOS 3.2.
If you need to configure your iPad application differently from your iPhone application, you can specify device-specific values for Info.plist
keys in iOS 3.2 and later. When reading the keys of your Info.plist
file, the system interprets each key using the following pattern:
key_root-
<platform>~
<device>
In this pattern, the key_root portion represents the original name of the key. The <platform> and <device> portions are both optional endings that you can use to apply keys to specific platforms or devices. Specifying the string iphoneos
for the platform indicates the key applies to all iOS applications. (Of course, if you are deploying your application only to iOS anyway, you can omit the platform portion altogether.) To apply a key to a specific device, you can use one of the following values:
iphone
- The key applies to iPhone devices.
ipod
- The key applies to iPod touch devices.
ipad
- The key applies to iPad devices.
For example, to indicate that you want your application to launch in a portrait orientation on iPhone and iPod touch devices but in landscape-right on iPad, you would configure your Info.plist
with the following keys:
<key>UIInterfaceOrientation</key> |
<string>UIInterfaceOrientationPortrait</string> |
<key>UIInterfaceOrientation~ipad</key> |
<string>UIInterfaceOrientationLandscapeRight</string> |
For more information about the keys supported for iPad applications, see “New Keys for the Application’s Info.plist File.”
Of all the changes you must make to support both iPad and iPhone devices, updating your views and view controllers is the biggest. The different screen sizes mean that you may need to completely redesign your existing interface to support both types of device. This also means that you must create separate sets of view controllers (or modify your existing view controllers) to support the different view sizes.
For views, the main modification is to redesign your view layouts to support the larger screen. Simply scaling existing views may work but often does not yield the best results. Your new interface should make use of the available space and take advantage of new interface elements where appropriate. Doing so is more likely to result in an interface that feels more natural to the user and not just an iPhone application on a larger screen.
Some additional things you must consider when updating your view and view controller classes include:
For view controllers:
If your view controller uses nib files, you must specify different nib files for each device type when creating the view controller.
If you create your views programmatically, you must modify your view-creation code to support both device types.
For views:
If you implement the drawRect:
method for a view, your drawing code needs to be able to draw to different view sizes.
If you implement the layoutSubviews
method for a view, your layout code must be adaptable to different view sizes.
For information about integrating some of the views and view controllers introduced in iOS 3.2, see “Views and View Controllers.”
Any code that uses symbols introduced in iOS 3.2 must be protected by runtime checks to verify that those symbols are available. These checks allow you to determine if newer features are available in the system and give you the opportunity to follow alternate code paths if they are not. Failure to include such checks will result in crashes when your application runs on iOS 3.1 or earlier.
There are several types of checks that you can make:
For classes introduced in iOS 3.2, you can use the NSClassFromString
function to see if the class is defined. If the function returns a non-nil
value, you may use the class. For example:
Class splitVCClass = NSClassFromString(@"UISplitViewController"); |
if (splitVCClass) |
{ |
UISplitViewController* mySplitViewController = [[splitVCClass alloc] init]; |
// Configure the split view controller. |
} |
To determine if a method is available on an existing class, use the instancesRespondToSelector:
class method.
To determine if a function is available, perform a Boolean comparison of the function name to NULL
. If the result is YES
, you can use the function. For example:
if (UIGraphicsBeginPDFPage != NULL) |
{ |
UIGraphicsBeginPDFPage(); |
} |
For more information and examples of how to write code that supports multiple deployment targets, see SDK Compatibility Guide.
If your code needs to follow a different path depending on the underlying device type, you can use the userInterfaceIdiom
property of UIDevice
to determine which path to take. This property provides an indication of the style of interface to create: iPad or iPhone. Because this property is available only in iOS 3.2 and later, you must determine if it is available before calling it. The simplest way to do this is to use the UI_USER_INTERFACE_IDIOM
macro as shown below:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) |
{ |
// The device is an iPad running iPhone 3.2 or later. |
} |
else |
{ |
// The device is an iPhone or iPod touch. |
} |
Because resource files are generally used to implement your application’s user interface, you need to make the following changes:
In addition to the Default.png
file displayed when your application launches on iPhone devices, you must add new launch images for iPad devices as described in “Providing Launch Images for Different Orientations.”
If you use images, you may need to add larger (or higher-resolution) versions to support iPad devices.
If you use nib files, you need to provide a new set of nib files for iPad devices.
Your application icons must be sized appropriately for iPad, as described in “Providing Application Icons for iPad.”
When using different resource files for each platform, you can conditionally load those resources just like you would conditionally execute code. For more information about how to use runtime checks, see “Using Runtime Checks to Create Conditional Code Paths.”
Maintaining a single Xcode project for both iPhone and iPad development simplifies the development process tremendously by allowing you to share code between two separate applications. The Project menu in Xcode includes a new Upgrade Current Target for iPad command that makes it easy to add a target for iPad devices to your existing iPhone project. To use this command, do the following:
Open the Xcode project for your existing iPhone application.
Select the target for your iPhone application.
Select Project > Upgrade Current Target for iPad and follow the prompts to create two device-specific applications.
Important: You should always use the Upgrade Current Target for iPad command to migrate existing projects. Do not try to migrate files manually.
The Upgrade Current Target for iPad command creates a new iPad target and creates new nib files for your iPad project. The nib files are based on the existing nib files already in your project but the windows and top-level views in those nib files are sized for the iPad screen. Although the top-level views are resized, the command does not attempt to modify the size or position of any embedded subviews, instead leaving your view layout essentially the same as it was. It is up to you to adjust the layout of those embedded views.
Creating a new target is also just the first step in updating your project. In addition to adjusting the layout of your new nib files, you must update your view controller code to manage those nib files. In nearly all cases, you will want to define a new view controller class to manage the iPad version of your application interface, especially if that interface is at all different from your iPhone interface. You can use conditional compilation (as shown below) to coordinate the creation of the different view controllers. If you make few or no changes to your view hierarchy, you could also reuse your existing view controller class. In such a situation, you would similarly use conditional compilation to initialize your view controller with the appropriate nib file for the underlying device type.
The following example includes the iPad view controller code if the Base SDK of the target is set to iPhone Device 3.2 or later. Because the Base SDK for your iPhone application target would be set to an earlier version of the operating system, it would use the #else
portion of the code.
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200 |
MyIPadViewController* vc; |
// Create the iPad view controller |
#else |
MyIPhoneViewController* vc; |
// Create the iPhone view controller |
#endif |
In addition to your view controllers, any classes that are shared between iPhone and iPad devices need to include conditional compilation macros to isolate device-specific code. Although you could also use runtime checks to determine if specific classes or methods were available, doing so would only increase the size of your executable by adding code paths that would not be followed on one device or the other. Letting the compiler remove this code helps keep your code cleaner.
Beyond conditionally compiling your code for each device type, you should feel free to incorporate whatever device-specific features you feel are appropriate. The other chapters in this document all describe features that are supported only on iPad devices. Any code you write using these features must be run only on iPad devices.
For more information on using conditional compilation and the availability macros, see SDK Compatibility Guide.
Creating an iPad application from scratch follows the same process as creating an iPhone application from scratch. The most noticeable difference is the size of views you create to present your user interface. If you have an idea for a new application, then the decision to start from scratch is obvious. However, if you have an existing iPhone application and are simply unsure about whether you should leverage your existing Xcode project and resources to create two versions of your application, or a universal application supporting all device types, then ask yourself the following questions:
Are your application’s data model objects tightly integrated with the views that draw them?
Are you planning to add significantly more features to the iPad version of your application?
Is your application device-specific enough that porting would require changing large amounts of your code?
If you answered yes to any of the preceding questions, then you should consider creating a separate Xcode project for iPad devices. If you have to rewrite large portions of your code anyway, then creating a separate Xcode project is generally simpler. Creating a separate project gives you the freedom to tailor your code for iPad devices without having to worry about whether that code runs on other devices.
If you are porting an application that uses the MPMoviePlayerController
class of the Media Player framework, you must change your code if you want it to run in iOS 3.2. The old version of this class supports only full-screen playback using a simplified interface. The new version supports both full- and partial-screen playback and offers you more control over various aspects of the playback. In order to support the new behaviors, however, many of the older methods and properties were deprecated or had their behavior modified significantly. Thus, older code will not behave as expected in iOS 3.2.
The major changes that are most likely to affect your existing code are the following:
The movie player controller no longer manages the presentation of the movie. Instead, it vends a view object that serves as the playback surface for the movie content.
Calling the play
method still starts playback of the movie but it does not ensure that the movie is visible.
In order to display a movie, you must get the view from your MPMoviePlayerController
object and add that view to a view hierarchy. Typically, you would do this from one of your view controllers. For example, if you load your views programmatically, you could do it in your loadView
method; otherwise, you could do it in your viewDidLoad
method. Upon presenting your view controller, you could then begin playback of the movie or let the user begin playback by displaying the movie player’s built-in controls.
If you want to present a movie in full-screen mode, there are two ways to do it. The simplest way is to present your movie using an instance of the MPMoviePlayerViewController
class, which is new in iOS 3.2. This class inherits from UIViewController
, so it can be presented by your application like any other view controller. When presented modally using the presentMoviePlayerViewControllerAnimated:
method, presentation of the movie replicates the experience previously provided by the MPMoviePlayerController
class, including the transition animations used during presentation. To dismiss the view controller, use the dismissMoviePlayerViewControllerAnimated
method.
Another way to present your movie full-screen is to incorporate the view from a MPMoviePlayerController
object into your view hierarchy and then call its setFullscreen:animated:
method. This method toggles the movie presentation between full-screen mode and displaying the movie content in just the view.
In addition to the changes you must make to your existing code, there are several new features that applications running in iOS 3.2 can use, including:
You can change the movie being played programmatically without creating a new movie player controller.
You can programmatically start, stop, pause, and scrub (forward and backward) through the current movie.
You can now embed additional views on top of the video content.
The movie player controller provides a background view to which you can incorporate custom background content.
You can set both the start and stop times of the movie, and you can have the movie play in a loop and start automatically. (Previously, you could set only the start time.)
You can generate thumbnail images from frames of the movie.
You can get general information about the current state of the movie, including its duration, current playback position, and current playback rate.
The movie player controller now generates notifications for most state changes.
Last updated: 2010-04-13