Basic Usage

XCConfig is an external xcode build settings.

You can list build settings with the following format,

BUILD_SETTING_NAME = value

Conditional values are available.

ONLY_ACTIVE_ARCH[config=Debug][sdk=*][arch=*] = YES

You can access the value in Swift

let object = Bundle.main.object(forInfoDictionaryKey:key)

Separate configuration/code

Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires strict separation of config from code. Config varies substantially across deploys, code does not.

Bad

The following code has constant values in code.

import Foundation
 
#if DEBUG
let apiBaseURL = URL(string: "https://api.staging.example.com")!
#else
let apiBaseURL = URL(string: "https://api.example.com")!
#endif

It’s a common statement when you use different values per environments. It’s a configuration by coding. In this example, apiBaseURL is a single value, but the code is more complicated than it should be. By introducing XCConfig, you don’t need to write the entire code above.

Good

Let’s say, you have 2 XCConfigs, Debug.xcconfig, Release.xcconfig.

API_BASE_URL = api.staging.example.com
API_BASE_URL = api.example.com

In Swift, you can just fetch and use the value.

guard let url = Bundle.main.object(forInfoDictionaryKey:"API_BASE_URL") else {
    return
}
 
URLSession...

Code is consistent in any environments and the value varies according to the environment.

Important Notes

XCConfig is public file like header files. It’s visible in the binary package. You must never put credentials or classified information there.

Managing Secret Values

As a general advise, don’t use xcconfig files to store secrets like API keys or other credentials For more information.

Nevertheless, if you really need to manage secret values in XCConfig, it’s doable without checking in XCConfig files on VCS(git, subversion, etc.)

In .gitignore(if you are using git),

path/to/Release.xcconfig
path/to/Debug.xcconfig

Still you will be able to access the values through Bundle API. It works like .env

References