Derrick Ho
Dec 27, 2016 · 2 min read

Xcode Custom Environment Variables

Some time ago I wrote about Super Preprocessor Directives in an attempt to conditionally compile code from a dynamic framework. Dynamic frameworks are meant to be black boxes and my intent was for any project to be able to toggle on and off some functionality based on the desires of the parent. However, I now believe that this was the wrong approach; I was in actually looking for Environment Variables.

Environment variables are values that can be added to your program at runtime. Imagine you wrote a dynamic framework and wanted to offer the ability to toggle a verbosity options. You can use Environment Variables to set these options in a very simple way.

  1. Edit scheme
  2. Add the Key (i.e. verbose_level) and Value (i.e. silent)
Image for post
Image for post

Then you can access this value using ProcessInfo

ProcessInfo.processInfo.environment["verbose_level"]

ProcessInfo.processInfo.environment will give us a dictionary<String,String> which means we can use it to our advantage.

Our dynamic framework will have access to this dictionary which means we can toggle our verbosity levels if we choose to.

if ProcessInfo.processInfo.environment["verbose_level"] == "verbose"
{
print("debug statements")
}

This is a great hidden gem in xcode because now our target application can deliver information to our dynamic framework without doing any modifications programmattically.

— — — -

Also…

Using hard coded strings isn’t the best practice. We should instead use enums

enum EnvironmentVariables: String {
case verbose_level
var value: String {
let v = ProcessInfo.processInfo.environment[rawValue]
return v ?? “”
}
}
// Use case
if EnvironmentVariables.verbose_level.value == "verbose" {
print("debug info")
}

There are two problems with this actually:

  1. Because environment keys are global we should namespace them to prevent overriding some other value.
  2. Difficulty adding new cases

Fixing number one is easy:

enum EnvironmentVariables: String {
case MYAPP_verbose_level // add namespace
}

We just need to add “MYAPP_” to verbose_level in the Environment Variable in Xcode.

Fixing number two means we can’t using enums. Instead we must use structs.

struct EnvironmentVariables: RawRepresentable {
var rawValue: String
static let dnthome_verbose_level = EnvironmentVariables(rawValue: "dnthome_verbose_level")
var value: String {
let v = ProcessInfo.processInfo.environment[rawValue]
return v ?? “”
}
}
// an extension that exists elsewhere
extension EnvironmentVariables {
static let dnthome_something = EnvironmentVariables(rawValue: "dnthome_something")
}

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

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