iOSアプリ開発における環境切り替え（Debug⇔Release）方法まとめ

iOSに限らず、アプリ開発においてAPIのURLやアクセスキーといった**環境変数を開発用ビルドとリリース用ビルドで切り替えられる**ようにしておくことは重要です。
XCodeでこれを実現する方法にはいくつかの選択肢があると思います。

本記事では、今のところ私がシンプルで良いと思っているやり方をご紹介したいと思います。

## 環境変数を切り替える
ここでは開発用ビルドとリリース用ビルドでAPIのURLを切り替えることを例とします。

### Configuration
XCodeではアプリのビルド設定は`Configuration`と呼ばれており、デフォルトでは`Debug`と`Release`の2つが作成されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/a184291e-a381-7bfe-f179-43bc5090efb3.png)

基本的にアプリの開発中は`Debug`を使用します。
XCodeメニューからProduct > Scheme > Edit Scheme...を開くと、ビルド設定として`Debug`が指定されていることがわかります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/247b2b77-ef4a-1857-a45f-eddc37774e6b.png)

### 環境変数の設定
ここで紹介する環境変数の切り替え方法では、登場人物は以下の3つです。

- ターゲットのBuild Settings
- Info.plist
- Configuration構造体

環境変数（ここではAPIのURL）を参照する流れはこんな感じです。

```
APIクライアント -> Configuration構造体 -> Info.plist -> ターゲットのBuild Settingsに定義された環境変数
```

#### ターゲットのBuild Settings
まず、ターゲットのBuild Settingsに環境変数を定義します。
以下のように、ターゲットを選択してBuild Settingsタブ開き、Add User-Defined Settingをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/52efda72-1ed4-b2d3-bf20-54379e56441e.png)

すると、Build Settingsの一番下のUser-Defined欄に項目が追加されるので、名前を`SE_API_URL`に変更します。
そして、ビルド設定ごとに値を入力できるようになっているので、`Debug`には開発用APIのURL、`Release`には本番用APIのURLを入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/530d952d-f845-5e85-7381-0fd2df758f92.png)

> 他の環境変数と名前がかぶらないようにプレフィックスをつけると良いようです。ここではSwitchEnvというプロジェクト名の頭文字を取ってから`SE`というプレフィックスをつけました。

#### Info.plist
次に、Info.plistから先程定義した`SE_API_URL`を参照します。

以下のように`AppConfig`というDictionary型の項目を追加します。
そしてその中に`ApiUrl`という項目を追加し、値として`$(SE_API_URL)`を入力します。
`$()`でBuild Settingsに定義された環境変数を参照することができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/348fc03c-9883-6f59-aec6-24a0477cfd3e.png)

> 今回は環境変数を一つだけ定義しますが、今後変数が増えていくことを見越して整理しやすいようにするために`AppConfig`という入れ物を作っています。

#### Configuration構造体
環境変数をソースコードから参照するために、`Configuration`という名前の構造体を作成します（名前が紛らわしいですが）。
この構造体はシングルトンとして実装し、他のコードはこのシングルトンインスタンス経由で環境変数を参照します。

```swift
import Foundation

struct Configuration {
    static let shared = Configuration()

    private let config: [AnyHashable: Any] = {
        let path = Bundle.main.path(forResource: "Info", ofType: "plist")!
        let plist = NSDictionary(contentsOfFile: path) as! [AnyHashable: Any]
        return plist["AppConfig"] as! [AnyHashable: Any]
    }()

    let apiUrl: String

    private init() {
        apiUrl = config["ApiUrl"] as! String
    }
}
```

APIクライアントは以下のようにURLを参照します。

```swift
let url = URL(string: Configuration.shared.apiUrl)!
```

## アプリ名、バンドルIDの切り替え
ビルド設定ごとに別々のアプリとしてインストールできるようにしておくと便利です。
ここではそのやり方について紹介します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/2f7f16cd-03ed-9e16-dcb5-1292e5059075.png)

iOSではバンドルIDでアプリを一意に識別するので、開発用ビルドとリリース用ビルドでバンドルIDを分ければ別々のアプリとしてインストールできることになります。

まず、ターゲットのBuild SettingsでProduct Bundle Identifierという項目を探します。
そして、`Debug`の方の値の最後に`-debug`というサフィックスを追加します。
これで`Debug`と`Release`でバンドルIDが変わります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/2bdf4cbc-89bd-da5a-9643-ebc719e3584f.png)

アプリの表示名も別々になるようにしましょう。
ターゲットのBuild Settingsに`SE_BUNDLE_DISPLAY_NAME`という環境変数を追加します。
そして`Debug`と`Release`で別々の名前を入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/10b4c21d-f652-5632-6b9a-967908012ac2.png)

次に、Info.plistに`Bundle display name`という項目を追加し、`$(SE_BUNDLE_DISPLAY_NAME)`という値を入力します。
これでアプリの表示名がビルド設定ごとに変わります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/5108755b-6bf3-c8e8-c3cb-f33c8a583954.png)

## Firebaseプロジェクトの切り替え
環境変数の切り替えという点で共通するので、以前書いた記事のリンクを載せておきます。

[開発版とリリース版でFirebaseのGoogleService-Info.plistを切り替える](https://qiita.com/takehilo/items/4437bed61665e2c955ed#%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%81%AF%E4%B8%80%E3%81%A4%E3%81%A7configuration%E3%81%A7%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B%E5%A0%B4%E5%90%88)

## アプリアイコンの切り替え
アプリアイコンの切り替え方法は以下の記事で知りました。
ビルド設定の切り替えについても以下の記事の方が幅広く紹介されてますね。

[XcodeでDevelop/Staging/Release環境を上手に切り分ける方法](https://qiita.com/Todate/items/a2e6a26731c79bd23e02#%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E3%)

## 参考記事
- [Effective Environment Switching in iOS](https://blog.usejournal.com/effective-environment-switching-in-ios-6df0b08e9556)