Put env variables in build settings
If you want the environment variable to persist during archive, create a User-Defined build setting
:

Each target can have a different value. I've named this one RELEASE_ENV
with dev
, staging
, and prod
values for each of my targets.
Add to Info.plist
We can't read these build settings directly, but we can access them through our Info.plist
.
Add an Environment variables
key that exactly matches the one we created in Build Settings. Here we give it a value $(RELEASE_ENV)
so that it imports the build setting we created earlier.

You can then access it in code using:
let envDict = Bundle.main.infoDictionary?["LSEnvironment"] as! Dictionary<String, String>
let envStr = envDict["RELEASE_ENV"]!
print(envStr) // Outputs: "staging"
This is probably one of the only places you'll want to use !
, that way you'll crash if the environment variable isn't there. This will persist even outside of Xcode runs.
(Optional) Set up an EnvManager to use in code
User-Defined build settings
is a pretty clunky place to manager tons of separate environment variables for all your backend endpoints and other env dependent strings. You can put those in an EnvManager
WARNING: Don't store sensitive data, such as api keys, like this. Use something like AWS KMS instead.
class EnvManager: ObservableObject {
static let shared = EnvManager()
private init() {
// We use ! here because we'd want to crash if missing
let envDict = Bundle.main.infoDictionary?["LSEnvironment"] as! Dictionary<String, String>
let envStr = envDict["RELEASE_ENV"]!
env = EnvType(envStr: envStr)
}
@Published var env: EnvType
enum EnvType {
case dev
case staging
case prod
// Read the xcode schema env var string
init(envStr: String) {
switch envStr {
case "dev":
self = .dev
case "staging":
self = .staging
case "prod":
self = .prod
default:
fatalError("Invalid env")
}
}
// Make a separate computed var for each env dependent value
var backendUrl: String {
switch self {
case .dev:
return "http://localhost:8080/"
case .staging:
return "https://staging-api.example.com/"
case .prod:
return "https://api.example.com/"
}
}
}
}
Usage
print(EnvManager.shared.env.backendUrl) // "https://staging-api.example.com/"