Build Configuration Management with Swift
You’ve undoubtedly read that Swift doesn’t have a preprocessor and may have concluded from that you can no longer use code techniques such as:
#define SERVER_URL "https://production-server/"
#define SERVER_URL "https://staging-server/"
You wouldn’t necessarily be faulted in thinking this, in that
#define is gone, as well as one my particular favorites
#if 0 (see our post here on how to use
/* */ in Swift to comment out large blocks of code, even if they are nested). Nor are there macros in the C preprocessor sense. There is however support for the
#if FLAG “preprocessor” statement and it can still be used as above with a slight modification. Let’s take a look:
let SERVER_URL = "https://production-server/"
let SERVER_URL = "https://staging-server/"
Notice we just replaced our inner preprocessor
#define statements with the constant declaration syntax of Swift (i.e.,
To set the
RELEASE_VERSION flag go to your target’s Build Settings page and search for swift flags. You should see the following filtered out:
Click on the Other Swift Flags line to show the disclosure triangle, and then click on the disclosure triangle to bring down the options for setting flags for either the Debug or Release build (I’m assuming here these are your two build configurations, if you’re an advanced user and managing many different build configurations then you’ll select the one you want to set flags for).
Click on the build configuration you are interested in and bring up the dialog box for entering individual flags and add each flag one by one using the syntax
-DFLAG_NAME with no spaces between any of the characters. Using underscores is fine, and to be honest I haven’t tried using “special characters” or created emojified (is that a word?) flags.
Again, this is not the same as the C preprocessor, so you can’t do things like this:
-DRELEASE_VERSION=1. Keep it simple and treat the flags as present or not. Our above code was combined with a simple
println("Launching with SERVER_URL as \(SERVER_URL)") in the
didFinishLaunchingWithOptions function, and as expected the console printed
Launching with SERVER_URL as https://production-server/ when building with the Release configuration.
Note: You’ll notice that we used the target Build Settings page. You can if you have multiple targets (say, for Apple Watch support), use the project’s Build Settings to apply to all of the targets saving those you explicitly override.
No, there is not a preprocessor Swift, and along with it no support for macros and the like, but basic build configuration flags are supported and one can compile in one set of constants or another using this technique. I frequently have 4 or 5 different build configurations I work with:
- Production Debug (use the production server with debug logs enabled)
- Staging Debug (use the staging server with debug logs enabled)
- Production Release (use the production server with optimization on and debug logs off)
- Staging Release (use the staging server with optimization on and debug logs off)
- No iAd (if I’m taking screenshots for the AppStore and don’t want the iAd banner in the way)
All of this can be accomplished by using
#if and Swift build flags alongside the familiar build configurations and schemas.