Sharing source in Xcode (Lite/Paid, reskinning…)

Guides | Tutorial By 4 years ago

Whenever you have a couple of apps that are extremely similar, it will make sense to share the code between the two. For example, a Lite version and a Paid version of the same app, or the same app skinned differently for different clients.

At first you might be tempted in duplicating the project. Don’t. If the code splits then it’s going to be a nightmare copying changes between two places, or even just having them in two separate projects.

Most projects have a single target, or possibly two if you do Unit Testing. Instead of duplicating the entire project, you can simply duplicate your target, change a few details around a presto, you have two apps with the same codebase.

It’s quite easy, but here are the steps involved. Backup your project just in case you make a mess of things.

1. Duplicating a target

First select the project then right click your app target then duplicate it. Another will appear, you will probably want to rename this. Another info plist will have also been generated for you. Each target has it’s own, so you can add unique things such as app id, version number and app name in here.

2. Some cleanup

When you rename the target it wont rename any of the other files. You probably wont want a bunch of ‘xxx copy’ targets hanging around, so if you want you can clean these up by selecting the new target, choosing the build settings section then filtering by ‘copy’. If you change references to files such as the info plist, the file itself will also need to be renamed.

3. Running the project

To choose a target to run, hold down on the current target at the top left of Xcode, select your desired target. Run the project and the current target will get executed.

If it still lists your new target as ‘xxx copy’ in the target drop down, quit Xcode, right click on your .xcodeproj file and choose show package contents. Delete everything inside xcuserdata, then right click project.xcworkspace, show package contents and delete everything inside xcuserdata again. Reopen your project and everything should be fine. Don’t worry these files aren’t vital, they store simple things like your last window size, which file you last had open etc etc.

4. Split logic

With the setup out of the way, you’re going to want to enable or restrict certain things depending on which target you are compiling. I’ll show an example of this by presenting an alert on launch, showing which code is being compiled. I’m going to treat my MultiTarget (seen in the screenshots) as a full version of the app, and the OtherTarget as a lite version. First open up the build settings for one of the targets. Look for the “preprocessor macros” row. Open the field and in the editor in the first row write $(inherited), then add another row and write FULL_VERSION. The inherited part just means it will use any macros from build settings higher up. FULL_VERSION is now a defined macro that can be checked anywhere in code to determine which target is being run. Obviously you only want to apply this macro to only one of your targets.

Now anywhere in your code you can simply write

//	Full version code
//	Lite version code

Here’s what I’ve done in my example. You can download it here.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

	NSString* message = @"Full version";
	NSString* message = @"Lite version";

	[[[UIAlertView alloc] initWithTitle:Nil
			otherButtonTitles:nil] show];

    return YES;

5. The future…

When adding new classes, in the window that pops up when you choose where to save it, tick both targets. This just means the file will be compiled on both.