Run multiple versions of your iOS app side-by-side!

One of my sides projects is an app called Taco Finder — an app that helps find the best nearby tacos.

Taco Finder needs to be able to run against two different backend environments. Until now I've just been hacking the code to switch between backends, but this is cumbersome and time consuming.

Ideally, I'd like to have two different versions of the app installed at the same time.

There are few times where having two versions of the same app installed at the same time might be helpful:

  • One version of that app that connects to Staging servers and another that connects to Production servers

  • One version that uses an Apple Developer Enterprise team for beta testing, but needs to switch to a different Apple Developer Team for the App Store release

  • A Release and Debug that each have their own slightly different configurations or features

This is a tutorial that will help you install two versions of your app installed at the same time!

What is a bundle ID?

In iOS, every app has a bundle ID (sometimes also called an Application Identifier, App ID, Bundle Identifier, Product Bundle Identifier).

Every app needs a unique bundle ID and it must be registered at the Apple Developer Portal. You'll find those here:

The bundle ID essentially defines the app in iOS. If you change the bundle ID it becomes a different app, with a different icon, a different sandbox and a different location on the app grid. Only one instance of a bundle ID can only be installed on a device at any given time.

Given that we want two versions of Taco Finder installed, we'll need two different bundle IDs. One will be used for the Staging environment and the other for our Production environment.

My existing Taco Finder bundle ID is com.buddybuild.tacofinder.
We'll add another to the Apple Developer Portal for our staging environment called com.buddybuild.tacofinder-staging.

Using Build Configurations

In Xcode, Settings are grouped into Build Configurations.

We'll add a new Build Configuration for our Staging environment. It's pretty easy — though a little buried — to add another build configuration:

  • In the project editor, select a project
  • Click "Info" at the top of the project editor
  • In the "Configurations" section, click the Add button (+)
  • From the popup menu, select a configuration file to duplicate

Let's duplicate the (default) Release configuration and call it "Staging"

Using another Bundle ID

Next, we'll need to tie the Build Configuration to a new bundle ID.

To do so:

  • In the project editor, select your Target
  • Click "Build Settings" at the top of the project editor
  • Scroll to the "Product Bundle Identifiers" setting and expand to see all the Product Identifiers

Having added a new build configuration, a new row appears, and I can edit the Product Bundle Identifier associated with that build configuration.

Distinguishing between apps

We can now install two versions of Taco Finder on our device... but we won't be able to distinguish between the two! Ideally, we'd like to have two different icons and different specific to each version.

Creating a new icon.

Before I can switch icons based on configuration, I will have needed to create new iOS Icon Set in my Asset Catalog.

After the icon set has been created, reference it by:

  • In the project editor, select your Target
  • Click "Build Settings" at the top of the project editor
  • Scroll to the "Asset Catalog App Icon Set Name" setting and expand to see all
  • Select "Staging" and specify the name of the icon set you just created

Switching the App Display Name

I also want to vary the name of the app in the app grid when it's installed. The name of an iOS apps is a result of the CFBundleDisplayName property in the app's Info.plist.

To vary the name based on the Build Configuration, we're going to introduce a new User-Defined Setting, and update the Info.plist to reference it.

To do so:

  • In the project editor, select your Target
  • Click "Build Settings" at the top of the project editor
  • Click the '+' to "Add a User Defined Setting"
  • Choose a name for the new setting to use as a placeholder for the display name: "TACO_DISPLAY_NAME" in this example

  • Expand the setting and specify the name that you'd like to appear for your app ("Taco Staging" in this case)

Now, update the Info.plist to reference the new setting.

To do so:

  • Open the Info.plist in the "Supporting Files" folder of your project
  • Reference the user defined setting you created in the step above — $(TACO_DISPLAY_NAME) in this case.
  • Note: If you don’t see "Bundle Display Name" in the list, click the '+' to add it

Creating the Staging Scheme

The final step is to add a new scheme for my staging version. To add a scheme:

  • From the Product menu, choose Scheme and Manage Schemes. Then select the '+'
  • Specify the name for the scheme (Taco Staging in this case)
  • Share the scheme by checking the "Shared" box

Finally, update the build configuration referenced from the scheme — in both the Run and Archive tabs — so that we build with the Staging build configuration.

Building the extra scheme in buddybuild

Now we've got the Staging scheme, let's make sure we're building it in buddybuild so it's easy for me to install and send to my colleagues, and fellow taco foragers.

As you might expect, this part is straightforward with buddybuild.

Simply go to navigate to Settings (the "Gear" icon in the header bar), and switch on the new Taco Staging scheme.

Wrapping up

There are a lot of cases where you might want to have two versions of your app side-by-side on your phone. Adding an additional scheme with a different bundle identifier is the best way to do this.

Let us know if you have any great iOS dev tips, if there's anything else you'd like to read about next, or just what your favourite taco spot is (ours is La Taqueria here in Vancouver) 🌮 !