How to configure Xcode projects for different environments?

Today, I want to share different configuration techniques for Xcode projects with you for different environments like; development, beta, QA, pilot, production, etc.

First of all, ❗️ do not use targets for environmental configuration purposes.

Let’s start with creating a new Debug and Release configuration for each of our environments. Like; Development Debug, Test Release, QA Release, Test Debug, Production Release, etc.

Image for post
Image for post

Also for CocoaPods, we should update .Podfile for newly created configurations.

Image for post

Let’s create schemes for each configuration sets. Development, Test, QA, Production, etc. Make sure that we’re sharing those schemes and selected the right Build Configurations.

Image for post
Image for post
Image for post
Image for post

So, how to set different values for different configurations? App Name, Bundle Identifier, API URL, .framework file?

First things first.

Let’s start with basics like App Name, Bundle Identifier, Icon Set Name, etc. Every configuration set has to have a different name, bundle identifier, and maybe icon for easier recognization.

| Bundle Identifier    | App Name    | Icon Set Name               |
| -------------------- | ----------- | --------------------------- |
| com.mycomp.myapp | MyApp | Original Icon |
| com.mycomp.myapp.dev | Dev - MyApp | Development Icon |
| com.mycomp.myapp.qa | QA - MyApp | Photo of one of the testers |
Image for post
Image for post
Image for post

We also need to create our own properties for other purposes. API URL, API Key, maybe another Info.plist, .so, or another framework?

There are 5 ways of achieving this. User-Defined settings, Xcode configuration files, multiple Info.plists, preprocessor macros, and custom script phases.

  1. User-Defined Settings

✅ Easy

⛔️ Not readable, especially on conflicts at .xcodeproj file

⛔ ️Have to pass data to Info.plist

Image for post
Image for post
Image for post

Additional tip before the second option.

❗️Always log your build settings and environment variables. Also, keep your build logs with your .xarchives.

Image for post
Image for post
Image for post

2. Xcode configuration files

✅ Easily readable

✅ Easy to see changes in git

✅ Supports conditional properties

⛔ Have to escape manually

⛔ Have to pass data to Info.plist

Image for post
Image for post
Image for post
Image for post

3. Using different Info.plists

✅ Semi Readable

✅ Easy to see changes in git

⛔ If you make a change on the project that interests Info.plist. You have to copy change into all of Info.plists.

⛔ Sometimes doesn’t feel right.

Image for post
Image for post
Image for post

4. Preprocessor macros

✅ Most readable choice

✅ Best for quick, non-vital configurations. Like; changing log type for a framework.

✅ Can use the same macro for different configurations and combine them.

⛔ Can be broken with .xcodeproj file merges, changes.

Image for post
Image for post

5. Script Phases

✅ Best for changing frameworks, libraries, whole files, etc.

Easier to understand with a Firebase, GoogleService-Info.plist example.

Image for post
Image for post
Image for post
Image for post

Thank you for reading. If you have any thoughts please feel free to share them in the comments.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store