基本的な使い方

XCConfig は、Xcode のビルド設定を外部ファイルとして管理する仕組みです。

ビルド設定は次の形式で列挙できます。

BUILD_SETTING_NAME = value

条件付きの値も使えます。

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

Swift からは次のように値にアクセスできます。

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

設定とコードの分離

アプリケーションは、設定を定数としてコードの中に保存してしまうことがあります。これは Twelve-Factor への違反です。Twelve-Factor は設定とコードの厳密な分離を要求しています。設定はデプロイごとに大きく変わりますが、コードは変わりません。

悪い例

次のコードは、定数値をコードの中に持っています。

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

環境ごとに異なる値を使うときによく見かける書き方です。これはコーディングによる設定です。 この例では apiBaseURL は単なる 1 つの値ですが、コードは本来あるべき姿よりも複雑になっています。 XCConfig を導入すれば、上記のコードを丸ごと書かずに済みます。

良い例

例えば、Debug.xcconfig と Release.xcconfig の 2 つの XCConfig があるとします。

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

Swift では、値を取得してそのまま使うだけです。

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

どの環境でもコードは同じままで、値だけが環境に応じて変わります。

重要な注意点

XCConfig はヘッダーファイルと同じく公開されるファイルです。バイナリパッケージの中からも見えます。認証情報や機密情報を絶対に置いてはいけません。

シークレットの管理

一般的なアドバイスとして、API キーなどの認証情報のようなシークレットを xcconfig ファイルに保存するのはやめましょう。

それでも、どうしても XCConfig でシークレットを管理する必要がある場合は、XCConfig ファイルを VCS(git、subversion など)にチェックインしなければ実現可能です。

.gitignore に(git を使っている場合)、

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

これでも Bundle API を通じて値にアクセスできます。.env と同じような仕組みです。

参考リンク