Xcodeで本番・ステージング・開発などの環境を分ける方法

iOS開発において、環境別にアプリ名やアイコンを変えたり、APIの向き先やログの出力先を変えたりすることが多いですよね。

そういう場合にどう切り分けていくのかの方法を説明します。

準備と基本設定

準備

まずはプロジェクトを作成します。

Xcode

Single View Appで問題ないです。

ここではどれだろうとあまり関係ないのでプロジェクトが作成できれば大丈夫です。

モグモグさん

すでにプロジェクトを作成していたり、既存のプロジェクトがある場合はこのステップは不要だよ👍

基本設定

初期の設定でConfigurationsDebugReleaseというものがあります。

Xcode configurations

まずは、このConfigurationsに本番前の環境用ということでStagingを追加していきましょう。

ここではDebugを開発用Stagingを本番前の環境用Releaseを本番用としましょう。

MEMO
環境名は自由です。

Duplicate "Debug" Configurationを押してStagingを作成します。

Xcode設定

作成後はこのようになっていればOKです。

Xcode設定結果

続いてBuild Settingsを設定していきます。

下の画像のように Active Compilation Conditionsと検索します。

Xcode検索

Stagingの箇所を、STAGINGに書き換えます。

XcodeのStagingを追加

この段階で、ソースコード上で環境ごと条件分岐ができるようになります。

#if DEBUG
  print("Hello, World! from DEBUG env!")
#elseif STAGING
  print("Hello, World! from STAGING env!")
#else
  print("Hello, World! from RELEASE env!")
#endif

続いてSchemeの設定をしていきます。

Manage schemesを選択して設定画面を表示します。

Xcode Manage Schemes

初期設定のSchemeをDuplicateしてコピーします。

Schemeコピー

任意でSchemeの名前を決めて、Build Configurationを作成したStagingに変更します。

Xcode Stagingに変更

同様にReleaseのバージョンも作成していきます。

すると、ビルド時にSchemeを選択できるようになりますね。

env-sample-appが開発用、Staging_Buildが本番前の環境用、Release_Buildが本番用になります。

モグモグさん

env-sample-appもDebug_Buildのように名前だけ変更してあげるといいかも!(今回はそのままにしているよ)

それぞれの環境でビルドすると環境を切り替えることができます。

上で書いたこのコードがそれぞれの環境で動くようになります。

#if DEBUG
  print("Hello, World! from DEBUG env!")
#elseif STAGING
  print("Hello, World! from STAGING env!")
#else
  print("Hello, World! from RELEASE env!")
#endif

ここまでで環境に応じて、処理を切り分けられるようになったので具体的によくあるケースに対応できるようにしていきましょう。

アプリ名を環境ごとに分ける

アプリ名を分けるには、User-Definedを追加していきます。

Levelsの右のプラスボタンを押して、Add User-Defined Settingを押します。

すると下の画像のようにUser-Definedの箇所に設定が一つ追加されるので

SAMPLE_DISPLAY_NAME_PREFIXとしてDebugではDEBUG、StagingではSTAGINGという値を設定してください。

設定完了したものが下の画像になります。

モグモグさん

SAMPLE_DISPLAY_NAME_PREFIXという名前は自由に設定してもいいよ!

設定が完了したら、TARGETSを選択してproduct nameと検索し

値を下の画像のように${SAMPLE_DISPLAY_NAME_PREFIX}-$(TARGET_NAME)としてください。

そうすると、それぞれの環境でSTAGING-env-sample-appのようにアプリ名が変更されます。

シュミレーターで、Stagingのschemeで実行するとこのようにアプリ名が変更されています。

Bundle Identifierを環境ごとに分ける

続いてBundle Identifierを環境ごとに分ける方法について説明します。

アプリ名を分ける方法とほとんど一緒になります。

モグモグさん

つまりUser-Definedで追加した変数を埋め込んで利用でくるということ! 応用ができそうだね!

まずは、User-Definedを追加していきましょう。

手順はアプリ名の時と同様です。

SAMPLE_BUNDLE_PREFIXという名前で環境ごとに設定しました。

Releaseは既存のままにしたいのでそのままにしています。

続いて定義したUser-Definedの値を利用してBundle Identifierを環境ごとに切り替わるようにしていきます。

TARGETSbundleと検索するとProduct Bundle Identifierが存在しているのでenv-sample-app.env-sample-app${SAMPLE_BUNDLE_PREFIX}としてあげます。

${SAMPLE_BUNDLE_PREFIX}の前の部分は、皆さんそれぞれのものになっているので合わせなくて大丈夫です。

すると、それぞれの環境のBundle Identifierが変わっているのが確認できると思います。

一度それぞれのSchemeでビルドをしてみましょう。

Bundle Identifierが切り替わっているので別々のアプリとしてされているのがわかりますね。

環境変数を利用する

基本設定の箇所では、コード上で条件分岐を行なって処理を分けていましたがUser-Definedを利用すれば条件分岐を記述せずに環境ごとの変数を利用できます。

例としてAPIのURLを環境ごとに分けるケースで説明します。

まずはアプリ名やBundle Identifierを切り替えた時と同様にUser-Definedを追加しましょう。

今回は、API_HOST_URLとしました。

値はそれぞれの環境で変更しています。

続いて、今回はinfo.plistで定義したUser-Definedとマッピングしていきます。

info.plistを選択し、Information Property Listの右側にフォーカスを当てるとプラスボタンが表示されるので、押したのちにKeyをapi_host_urlに設定して、Valueを${API_HOST_URL}のように先ほど定義した値に変更します。

これで環境変数の設定は完了したのでコード上で呼び出してみます。

下のコードのように呼び出せるので、皆さんの環境でコードを書きSchemeごとにビルドするとログにそれぞれの環境ごとのAPIのURLが表示されていると思います。

let apiHost = Bundle.main.object(forInfoDictionaryKey: "api_host_url") as! String
print(apiHost)

こちらのやり方の方が条件分岐を書く必要がないのでよりシンプルにできますね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です