Setting up your Xcode project for multiple development environments (dev, staging, live)

Are you in the habit of commenting out and uncommenting your API BASE URL (as shown below) whenever you want to build your project for Dev, Staging or Live environments? Then, this article is for you.

Maybe you don’t do that, maybe you just wish you could easily build your projects with any of these environments without making changes to your code always, then this article would surely help you figure that out.

BASE URLs

As you can see above, there are three base URLs, one for Dev, Staging and Live API environment respectively. With this, you need to comment out and uncomment whenever you wish to build for these environments, NOT COOL!

dean winchester GIF

With the use of Xcode Configurations, Custom Flags and Schemes, we can eradicate having to manually do this and make the process more efficient. Let’s see how!


Add Configurations

Usually, Xcode comes with two default configurations, Debug and Release. We can edit or add more. Let’s see how.

  • Go to your project settings by clicking on the project name from the left Xcode Navigator.
  • Under the Info tab, go to the Configuration section. You will notice the Debug and Release configurations.
  • Click on the + button below the configurations to view available options. Select Duplicate “Debug” configuration. With this, you will notice one more configuration added. Why did we duplicate Debug instead of Release? We did that so we could use Debug configuration for both Dev and Staging environment, and Release configuration for the Live environment.
  • Edit and change the first debug configuration name to Dev and the second to Staging. With that, you should have your configurations as shown below.
Xcode configurations

Add Custom Flags

Usually, Xcode comes with two default flags, DEBUG and RELEASE. With these, Xcode knows what configurations to use for your app when you run it or archive it. We can add more flags or edit the existing ones. Let’s see how.

  • Still on the project settings page, select Build Settings
  • Search for “flags” and scroll down to Swift Compiler – Custom Flags section. You should see your defined configurations (Dev, Staging, Release) listed with their assigned flags on the right.
  • Notice both Dev and Staging configurations have the DEBUG flag, this is because we are using the same configurations files for both, which is fine. Also, it gives you the flexibility of providing custom implementations that is specific to debug builds (Dev and Staging) within your code. So it’s a win-win 😉
  • Now, let’s add specific flags for each of these configurations. Double click the space on the right side of the Dev configuration, select the + button to add more flags. Add DEV.
  • Also, Double click the space on the right side of the Staging configuration, select the + button to add more flags. Add STAGING.
  • Finally, for Release configuration, we will be using the RELEASE flag. So if not added already, same way as above, add RELEASE. You can also decide to add specific flag like LIVE. But I will keep mine as RELEASE.

Now that you are done with that, your flags should look like below:

Custom Flags

Using the flags

Now, let’s make use of the flags we’ve created, so it’s time to get back to our not-so-good code and refactor it. With those flags created, we can specify different base urls and let Xcode do the work of compiling the right one for us when we build our project. (We will get to see how Xcode knows which one to use later in the article)

Base urls with flag

As you can see above, we are basically using the flags as conditions to return the proper base url for each case. You can also make use of a function that returns the expected value. Simple right?

Creating Schemes

This is kinda like the final stage of this setup. Here we want to add schemes that will allow us to run the same project, but for different builds/configurations. Meaning, we want to be able to run our app as APP_NAME-Dev, APP_NAME-Staging or APP_NAME-Live, just with one or two button clicks. Let’s go ahead and do that.

  • Select Manage Schemes… from the project scheme dropdown on the top left corner of Xcode (as shown below)
Scheme dropdown
  • Select the only existing scheme from the list and click on the Edit… button
  • On the popup, select Duplicate Scheme button. This will create another copy of the scheme. Rename the scheme from “Copy of APP_NAME” to APP_NAME-Staging. For me, my app name is ProjectStructure, so the scheme becomes ProjectStructure-Staging.
  • Repeat the steps above and create another scheme, APP_NAME-Dev
  • Finally, go to the Manage Schemes popup and edit the first scheme we started with from APP_NAME to APP_NAME-Live.

With that you should have something like this in the Manage Scheme popup and the Scheme selection dropdown.

Manage Schemes
Monosnap 2020 06 21 23 44 19 1

Lastly, still on schemes, we will specify what configurations Xcode should use when we run any of these schemes.

  • Go to Manage Schemes…
  • Select one of the schemes, say APP_NAME-Dev, click on the Edit button. You should see the dialog with tabs on the left, as shown below
Edit scheme
  • Click on the Run tab, under Build Configuration option, select Dev
  • Click on the Test tab, under Build Configuration option, select Dev
  • Click on the Profile tab, under Build Configuration option, select Dev
  • Click on the Analyse tab, under Build Configuration option, select Dev
  • Click on the Archive tab, under Build Configuration option, select Dev
  • Close the popup

Straightforward right? Now select the other two schemes and repeat the steps above, but with Build Configuration as Staging for APP_NAME-Staging scheme and Build Configuration as Release for APP_NAME-Live scheme.

Adding extra sauce

Let’s make our app name say, APP_NAME-Dev for Dev, APP_NAME-Staging for Staging and APP_NAME for Live. Cool right?

  • Navigate to the project settings page
  • Click on the Build Settings tab
  • Select your Target
  • Search for “product name”. You should see a section, Package with product name as APP_NAME for each of your configurations.
  • Double-click on each of the names and append them with -Dev for Dev and -Staging for Staging. Leave Release as it is, as the Live Product name should be your APP_NAME.
Product names

Also, it would be nice to have different Bundle Identifiers for each of your different configurations. So let’s do that.

  • Still on project settings page
  • Search for “bundle identifier”. You should see a section, Package with bundle identifier as your default bundle identifier for each of your configurations.
  • Same way as we did above for product name, double-click on the each of them and append -Dev for Dev and -Staging for Staging, or anything you wish to use to differentiate them.
Bundle identifiers

Another sauce 😉 you can add is having different App Icons for each of the configurations.

  • Still on the project settings page
  • Search for “icon”. You should see a section, Asset Catalog Compiler – Options with Icon Set Name as your default AppIcon for each of your configurations.
  • Same way as we did above for product name and bundle identifier, double-click on the each of them and append -Dev for Dev and -Staging for Staging, or anything you might have named your icons in your asset catalog.
App Icons

That’s all! Now you can run any of the schemes and Xcode will do the work of compiling the right code and configurations for you. 😁

snoop dogg dancing GIF by Romy

You can also use the flags you’ve created to specify other behaviours in your app for different environments, apart from the network request use case we’ve used here.

NB: Another way you can handle different base urls in your project is to put them in different Info.plist files and specify these different Info.plist files for each configuration in your project settings page.


Thank you for reading. I hope you find this really useful. Feel free to drop your comments, reviews and suggestions.

Au revoir ✌🏽

nick jonas bai GIF