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/"