Building Flockwork: Creating targets for free and full versions in a single Xcode project

This is part in a series of blog articles explaining some of the interesting technical hurdles we encountered while building our new iPad puzzle game Flockwork.

    

We’ll soon be launching a Free version of Flockwork, so I wanted to explain how best to set up your Xcode projects if you’re planning to support two versions. The goals were:

  • 1. Keep everything in a single Xcode project
  • 2. Make it easy to share code and assets
  • 3. Keep file sizes of the compiled apps as small as possible

1. Setting up a second target
The first step is to duplicate your existing target (for example MyAwesomeGame). Right/command click the target and choose Duplicate.

OK, what did Xcode just do?

  • It created a new target called MyAwesomeGame copy
  • It added a new Info.plist
  • It autocreated a new scheme for building the project

First you’ll want to rename things more sensibly. Press ENTER with the new scheme highlighted and name it MyAwesomeGameFree.

Next, go into Build Settings for the MyAwesomeGameFree target and filter for two settings: first change “Product Name” to MyAwesomeGameFree.

Next, change the “Info.plist file” setting to MyAwesomeGameFree-Info.plist.

Of course, now you’ll also need to rename the file to match. You can also move it to a more sensible group, as Xcode dumps it in the root of the project by default.

Now is also a good time to modify the Info.plist, you may want to change:

  • the Bundle Identifier (to match whatever you created in iTunes Connect)
  • the icon files and default launch image
  • Bundle display name

Finally you can rename the autocreated scheme – go to Product>Manage Schemes and rename the scheme to MyAwesomeGameFree.

Time to test it works! Choose the correct scheme from the dropdown, and run!

2. Detecting the target at runtime

It’s likely there won’t be too much difference between your paid and full versions: for example in Flockwork, most of the game is similar, but we only have 20 levels in the free version versus 80 levels in the paid version. For places in the code where you need different behaviour, you can do a runtime switch. We defined a boolean like this:

#define IsFree ([[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"] isEqualToString:BUNDLE_ID_FREE])

Then it’s easy to write code like this:

NSString *path = IsFree?@"levels_free.plist":@"levels_full.plist";

3. Selecting which assets will be included in each target

Now you have multiple targets, you need to be careful when adding new files to the project. You’ve probably seen this dialog many times. When you add a new file to the project, you’ll now need to ensure the correct targets are checked: make sure both targets are checked if its a file used in both versions, but only one target is checked if its only used in one version.

What about files which are already added to your project? If you go to Build Phases>Copy Bundle Resources you can see a list of all the files compiled into the target. It’s important to remove any you’re not using. For example, leaving in a full-screen splash from the full versions in your free version could easily add 2MB to your final app size. If you’re trying to get under the 50MB over-the-air download limit, that’s a lot!

Flockwork is available now in the app store! If you’d like to know when we launch Flockwork Free, sign up to our mailing list at ReignGames.

Matt Mayer

Matt Mayer is a founder at ReignDesign. Matt is from the UK and was based in Shanghai for ten years. He is now living in Bangkok, Thailand.

9 comments

  1. Thank you so much – the only thing I had a problem with this was trying to figure out the bundle id – in the end, I used the bundle name.

    #define IsFree ([[[[NSBundle mainBundle] infoDictionary] objectForKey:@”CFBundleName”] isEqualToString:BUNDLE_ID_FREE])

  2. I don’t like the new info.plist being at the root location. So I moved into a sub folder under Resource. After that the compilation failed because it cannot find the moved info.plist file. It was still look at the root location. To fix that, select the target and the Summary tab. It will have a button for you to browse and locate the info.plist file. After that the compiler was happy. Hope this is useful to someone.

    1. That also works. I slightly prefer looking up the bundle id as it makes the logic very explicit for other developers, Cmd+clicking the IS_FREE will take you to the definition in code

  3. Wow ! this is exactly what I was looking for..I always have to make three apps(AppName-DEV,AppName-QA and AppName) with different app names,APIs,bundle identifiers,code signing identities and provisioning profiles using the same source code.The approach you explained here seems to makes my life easier and less human error prone.Kindly keep on coming up with articles like this.

Leave a Reply

Your email address will not be published. Required fields are marked *

Share this post