Setting Up Xcode Targets: How to Create Multiple iOS Builds with Different API Environments

August 28, 2018

When developing an application, mobile app developers most often follow the standard development life cycle pattern – development, testing and production. For each of these stages, we have different API environments. For instance, when the app is in the development stage, it will communicate with Testing and production each have their respective API environments, too. In this article, we will discuss how to use Xcode targets to put a proper iOS app build system in place.

Before jumping in, let’s start with a few basics.

Why do we have 3 different API environments?

Creating separate API environments for development, testing and production provides each built with its own database, code-base and other respective backend services. This allows developers to continue to work and make changes, even while the app is in testing mode, and ensures (beta) testers do not mess up the production database.

What if my backend doesn’t have multiple environments set up?

How do we deal with multiple API environments in iOS?

We create a Constants.swift file in the project and define a variable called baseUrl. When building the app for development or production, we change the value of this variable so that the respective API endpoint is used in the build, as shown below.

(Commenting & Un-commenting the baseUrl per the build environment.)

Though this process is quick and simple, it is also highly error prone due to the following reasons:

  1. If there are many variables that have to be changed per the build environment, it takes more manual effort from the developers to comment or un-comment the respective statements.
  2. It is likely that developers will forget to comment or un-comment one or more statements in this process, leading to unintended behavior or issues. Then they must spend time in debugging to find the culprits.

To avoid these issues and create a more sound build system, one can use Xcode targets. If you aren’t familiar with targets in Xcode, read about them here before continuing.

Step 1: Create a Target

We will need to create a new target for each of the API environments. Technically, Xcode doesn’t allow you to create a new target, so we will duplicate (Cmd + D) the default target and rename it, as shown below.

(Creating a duplicate target.)

Xcode will automatically create a new scheme for this target.

Step 2: Setting Custom Flags

To change the API endpoint based on the build target, first you’ll need to set a custom flag. Based on this flag, your code can update the variables accordingly.

  • Select Target → Build Settings.
  • Make sure All and Combined options are selected.
  • Search for Custom Flags.
  • Under Swift Compiler — Custom Flags →Active Compilation Conditions you will see Debug. Double click on the value DEBUG and you will get a pop-up with + & buttons. See image below.

(Updating the DEBUG flag to DEVELOPMENT.)
  • Click Change DEBUG to Development.

Why is it important to select these settings?

These settings will impact how your app uses respective environment variables when your app is compiled.

Step 3: Using Custom Flags

Open your Constants.swift file, use the DEVELOPMENT flag as shown below, and set your environment variables (like baseUrl) accordingly.

(Preprocessor flags.)

As seen in the image above, you can define all the environment variables that should be different for development, testing and production.

Step 4: Testing

Now, let’s do a simple test to verify that the baseUrl changes per the build settings.

  • Write a print() statement in any ViewControllerviewDidLoad() method to print baseUrl value.
  • Select Manage Schemes from the tool bar, set RunBuild Configuration to Debug as shown below.

(Setting the Run Scheme to Debug.)

(Verifying log to see that the baseUrl displays the DEVELOPMENT API endpoint.)

  • Similarly, let’s set the RunBuild configuration to Release, as shown below. Execute the application, and you’ll see the baseUrl as production environment endpoint.

(Setting the Run Scheme to Release and verifying log.)

That’s how we use Xcode targets to manage iOS builds with multiple API environment endpoints. Pretty easy, right?

One more thing!

If you install the development, testing, and production iOS builds on a single device all at once and test the builds, take note: After you have created a new target (by duplicating), you’ll need to enter unique values for the Display Name and Bundle Identifier, because no two apps on a device can have the same ones. To easily differentiate between the builds, you can use a different display name and app icon, as shown below.

(Development and Production builds on same device.)

To create these for each target build, go to BuildSettings, search for icon and change the value of Asset Catalog App Icon Set Name to the desired app icon file name.

Note: You must be cautious when adding new files, dependencies (pods) and iOS permissions in plist and CI systems. Be sure you are selecting all the targets you have created so that these files are compiled for all the targets, avoiding compiler issues.

If you liked this post and found it helpful, give me some claps! Please follow me on Medium! Follow AppIt Ventures for other similar articles.

Let's build something awesome.

Reach out to us to discuss app development services for your company. We'll get back to you within 24 business hours.

Send us a message
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.