Building one app from one code base is pretty straight forward (all other complexities of Xcode development notwithstanding, of course). Building more than one app from one code base is a bit less intuitive, however. Recently someone wrote about using git, a source code control tool, to manage multiple app versions. This is an interesting approach, but I think breaks down when you start needing to churn out say… 7 or 8 or more distinct renditions of the same app. It also suffers from then having multiple full copies of the code base to, one for each version. Bug fixes have to be applied to all of them. A current project with which I am involved is facing this challenge now: many apps from one code base. Here’s what we’re doing (so far) to keep the “pain” to a minimum in order to produce 7+ apps at once.
The project in question has an app (or course) that talks to a backend for its content. The app itself, if you strip away the UI, is really a framework for the content. The first incarnation of the app has access to all the content. We are now adding more versions of the app, which we will offer for a lower price or perhaps for free depending on the content available in each, which will provide access to well defined, but limited amounts of the same content. But the framework for all of these apps is really identical to the original app. That is to say, the code for the “smaller” apps doesnt need to be different*, only the content does, which is controlled by how each app interacts with the backend. (* Ok, so there are some changes to the code, but they really have been minimal to make it a little more generalized to support multiple apps.) So how’d we do it?
So far, I have started by duplicating the target of our main app once to prove the concept that we should be able to use multiple targets. That results in a new target with it’s own “Info.plist” equivalent file. That is basically the only new file, which you would expect, since each target will build a unique app with it’s own bundle identifier, bundle name, and all that. Of course, each unique target has it’s own set of build settings, which is a key to making this scheme work.
In our case, each version has an identifying, compiled-in, version number (if you will). So we accomplish that by defining a compile-time macro in the build settings:
Then in code, we can deal with this like so:
+(NSInteger)edition
{
#ifdef EDITION
return EDITION;
#else
return 1; // Effective edition of existing app
#endif
}
Multiple targets are great, but you might be wondering: how do I build them all at once? The answer is: use the command line! While the Xcode IDE does not seem to offer an easy way to build all targets with once click (which, by the way, would be nice if it did!), you can do this from the command line easily using xcodebuild (the same tool that Xcode actually uses behind the scenes).
The xcodebuild tool includes an option to build all targets. So with a single command, you can build all your targets:
xcodebuild -alltargets -configuration Debug
Xcodebuild has a lot of other options that lets you choose schemes, SDKs, etc. Type xcodebuild -help to see them all, or type man xcodebuild at the command line for the Unix man page, or check the Xcode help system for documentation.
It is worth noting that you can implement Continuous Integration (CI) systems to build your iOS apps, and they will likely include direct use of xcodebuild in a script launched by your CI server. (We don’t do this for this project, but in another life I lead we do.)
As this project progresses over the next few months, I’ll report again on any gotchas we run into, or any pleasant surprises for that matter.
Your thoughts? Let me know in the comments.