Building for multiple iPhone targets in XCode

| | Comments (1) | TrackBacks (0)
I've been exploring building for multiple iPhone targets using XCode. The goal is to keep the common code across targets in one place, rather than cutting and pasting. It's pretty straightforward and also very customizable.  A very interesting technique is using #if TARGET macros to control execution...

Interationalization
A very common reason for multiple targets is multiple locales.  The easiest is to make sure that all the strings are in local-specific files.  The documentation is very clear for this.  A big advantage is you can still keep the same target name. 

Different Target names
Another common need is for different target names.  For example, you might offer a lite version of your super whizbang application.  XCode supports different targets very well.  If you want to keep the same names of files, like nib files or icons, across targets, you'll have to put them in separate directories.  Then you use the correct directory.  You will probabably need to have different mainview nib files.  Changing the target is done by setting the Active Target in the target pulldown, the same place as the active sdk and debug or release.

Same files for different targets
I really wanted to have some files remain the same because most of the functionality was common.  There are generally 3 places you can control the functionality: compile-time, link-time, and run-time.

Compile-time
It turns out to be really easy to set objective-c macros for compile time.  In the build settings for all targets, you add a user-defined setting called OTHER_CFLAGS.  This contains any extra C flags, but we are interested in just defining something for the target.  XCode sets the target name in a ${TARGET_NAME} variable (note the squiggle brackets are for build variables.    We set the OTHER_CFLAGS to contain "-DTARGET_NAME=${TARGET_NAME}". 

Then in your code you can do
#if TARGET_NAME == myApp
#elif TARGET_NAME == myAppLite
#endif

This has the nice advantage that your runtime code will be smaller and faster than a runtime check.

Tip: if you want to see all the #defines for your files, set the OTHER_CFLAGS to "-g3 -save-temps -dD"

Linktime
You can choose which files to link depending upon which target by setting the files under the target in xcode.  Simple as that.

Runtime
At run time you get the name of the application from a variety of sources.  There's a good apple technical article on obtaining the localized application name.
The gist is
    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *appName = [[NSFileManager defaultManager] displayNameAtPath: bundlePath];
Then you can do the expected if/else comparison.

Strings
An interesting technique for using different strings depending up the application name is to combine the target name comparison with the NSLocalizedString function.  The preprocessor variant might be
#if TARGET_NAME == foo
    doSomething NSLocalizedString(@"FOOSomethingKey", @"");
#elif TARGET_NAME == bar
    doSomething NSLocalizedString(@"BARSomethingKey", @"");
#endif

This is perhaps a little less readable than we'd like.  The runtime version could do
   doSomething NSLocalizedString( /* appName compare */ ? @"FOOSomethingKey" : @"BARSomethingKey", @"");

0 TrackBacks

Listed below are links to blogs that reference this entry: Building for multiple iPhone targets in XCode.

TrackBack URL for this entry: http://www.pacificspirit.com/cgi-bin/mt/mt-tb.cgi/243

1 Comments

Comparing TARGET_NAME against a value always seem to returned true for me. According to the post below, this is not possible and an alternate solution is offered:

http://stackoverflow.com/questions/1027091/how-do-i-check-the-target-name-of-my-iphone-app-on-xcode

Leave a comment

About this Entry

This page contains a single entry by Dave Orchard published on January 27, 2009 7:34 PM.

Social Media types are spending a lot of time awarding themselves was the previous entry in this blog.

Active trading results: +1% in 50 days is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Categories