Swift(Xcode)でプリプロセッサを使う

概要

Xcodeでプリプロセッサによるソースの切り替えを行う方法

ObjectiveCなどのC系の言語の場合だと、

#ifdef DEBUG
    // 開発用の接続先
    let server = "api.development.push.apple.com"
#else
    // 本番用の接続先
    let server = "api.push.apple.com"
#endif

といった感じのことをSwiftでしたい場合の方法。 なお、Xcode8以降で有効

デバッグビルドかどうかの判別

Xcode8以降の場合は、コンパイル時のフラグとしてデフォルトでデバッグビルドにはDEBUGが付与されている

よって、

#if DEBUG
    // 開発用の接続先
    let server = "api.development.push.apple.com"
#else
    // 本番用の接続先
    let server = "api.push.apple.com"
#endif

とするだけで良い

独自の定義を使いたい場合

Build SettingsSwift Compiler - Custom Flagsの中のActive Compilation Conditionsの中に追加する

(デフォルトでは、DebugのConfigutationsのみにDEBUGが入っている)

例えば、ステージング環境のConfigurations(Staging)に専用のHOGEを付与したい場合は、

という感じにすればOK

ビルド設定の状態

上記の様に設定した場合、以下の環境変数に設定がされる

// 一つで設定した場合
SWIFT_ACTIVE_COMPILATION_CONDITIONS = HOGE;

// 複数で設定した場合
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG HOGE";

参考・古い方法(Xcode7以前)

Build SettingsSwift Compiler - Custom Flagsの中にはOther Swift Flagsという項目もある

ここはActive Compilation Conditionsが登場する前にシンボルを定義する際に使っていた場所である。独自の定義を追加するには-D HOGEと設定すれば先の設定と同じ状態になる

が、ビルドの種類(デバッグとかリリースとか)に応じて切り替えをしたい場合は、より適切なActive Compilation Conditionsに統一した方が良い

#defineは使えない

Swiftでは#defineのようにソース中で定義をすることはできない

#defineは柔軟すぎて困る(上書きされたり#undefができてバグる)こともあるので個人的にはこれで良いと思う

ただ、開発中などでわざわざ定義を触るのも大変な時には以下の感じで逃げている

let DEBUG = true        // #define DEBUG true と同義
let server: String = {
    return DEBUG
        ? "api.development.push.apple.com"
        : "api.push.apple.com"
}()

#defineとの違いは値の確定がコンパイル時ではなく、実行時に行われる点であるが、判定は初回のみなのでパフォーマンスへの影響は無視できる

開発環境