iPad

Using Xcodes build system for iPhone + iPad projects

Posted in Cocoa, iPad, iPhone on April 8th, 2010 by Christian – Be the first to comment

My iPhone app iVocabulary will be available for the iPad as a separate application, not as a universal app. This is because the iPad version should be a First Class application not a scaled-up “Economy” app (as mentioned here). There will be many classes that are shared between both applications and therefore I build the apps from one Xcode project.

To distinguish between the devices in code, Apple advises to use something like this:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
MyIPadViewController* vc;
// Create the iPad view controller
#else
MyIPhoneViewController* vc;
// Create the iPhone view controller
#endif

But this can get very tedious and error prone. If you’ve got classes that are mostly the same for both devices but differ in some methods, the Xcode build system comes to the rescue.

Lets assume your AppDelegate differs in one method that initializes a viewcontroller differently for both devices. You can build that method and surround both code blocks with the structure above. But there is a better way: You create two categories for your class: AppDelegate+iPhone and AppDelegate+iPad:

/// file AppDelegate.h
@interface AppDelegate {
MentionedViewController *_viewController;
}
- (void)initMentionedViewController;
@end

/// file AppDelegate.m
@implementation AppDelegate
- (void) applicationDidFinishLaunching {
...
[self initMentionedViewController];
}
@end

/// file AppDelegate+iPhone.m
@implementation AppDelegate (iPhone)
- (void) initMentionedViewController {
... do special iPhone stuff here ...
}
@end

/// file AppDelegate+iPad.m
@implementation AppDelegate (iPad)
- (void) initMentionedViewController {
... do special iPad stuff here ...
}
@end

The important part is to define the targets of the categories .m-Files via the targets tab in the info screen:

Screenshot Xcode Targets

Xcode "Targets" tab

During the build, the Xcode build system includes the correct file and the other one will be left out. This way you get the same result as if you used the #if-constructs but with much cleaner and more transparent code.