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
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", @"");
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];Then you can do the expected if/else comparison.
NSString *appName = [[NSFileManager defaultManager] displayNameAtPath: bundlePath];
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", @"");
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