iOSアプリのビルドTARGETを複数作る


## TARGETについて
TARGETはビルド設定のまとまりで、Xcodeでプロジェクトを作成すると自動で1つ作成される。
TARGETを複数用意することで、テスト用、本番用などを切り替えてアプリをビルドすることができる。
~~サーバー環境を複数用意する場合などは、TARGETも複数作成すると良い。~~

## TargetとConfigurationどちらを使うべきか <font color="Red">2019/12/17 追記</font>


Xcodeにはビルド設定を切り替える仕組みが、`Target`と`Configuration`の2種類存在する。
Targetの方がより詳細な設定ができるが、この記事に書いた内容は全て `Configuration` でも切り替えられる。

多くの場合、**Targetを複数作るよりConfigurationを複数作る方が運用が簡単である。**

ただし、以下のようなケースはConfigurationでは対応できないため、Targetを複数作成する。

- アプリに含めるリソース（画像）などを変えたい
- ウィジェットなどのエクステンションを作る

※ ウィジェットについては Configuration でも切り替える方法があるかもしれない。

## TARGETによって切り替えられるもの

必要であれば様々な設定をTARGETで切り替えられるが、主に以下をTARGETによって切り替える。

<dl>
<dt>Bundle Identifier</dt>
<dd>Bundle IdentifierをTARGET毎に変えることで、各TARGETでビルドしたアプリを別アプリとして同じ端末にインストールできる</dd>
<dt>アプリ名</dt>
<dd>ホーム画面に表示されるアプリ名をTARGETによって変えることができる</dd>
<dt>プログラム処理</dt>
<dd>TARGETによってプログラム処理を変えることができる。例えば、テスト用と本番用で通信先のURLを別にするなどといったことが可能</dd>
</dl>

## TARGETの作り方

既存のTARGETを右クリック、Duplicateを選択してTARGETを複製する。

![スクリーンショット 2018-03-21 12.09.15.png](https://qiita-image-store.s3.amazonaws.com/0/233769/0a2f62b9-1826-277e-04c3-6ca1529590b6.png)


TARGETを複製するとアプリの設定ファイルInfo.plistも複製されるが、こちらは削除する。
Info.plistを複数使うこともできるが、一つのInfo.plistを使いまわした方が管理が楽。

![スクリーンショット 2018-03-21 12.16.48.png](https://qiita-image-store.s3.amazonaws.com/0/233769/d7803321-b644-bfd5-fdec-91f5d98da2e4.png)

削除すると新しくできたTARGETはInfo.plistが未選択の状態になるため、General > Identiry にある`Choose Info.plist File...`のボタンから既存のInfo.plistファイルを選択する。

## Build Settingsなどの設定

TARGETには任意の名前をつけ、それぞれにBundle Identifierを設定する。
![スクリーンショット 2018-03-29 10.48.15.png](https://qiita-image-store.s3.amazonaws.com/0/233769/55d66a67-15d4-ee27-6249-0aed04e5cf51.png)

次に各TARGETのBuild Settingsの以下の値を編集する。

### Other Swift Flags

Other Swift Flagsに `-D TARGET名` を設定する。
この値はプログラム内でTARGET毎に処理を切り替えたい場合に、どのTARGETでビルドされているかを判定するために使う。（判定方法は後述）

![スクリーンショット 2018-03-29 10.49.59.png](https://qiita-image-store.s3.amazonaws.com/0/233769/cad31426-43b7-2aa4-8cd4-8499dd583e3d.png)

### DISPLAY_NAME
TARGET毎にアプリの表示名（ホーム画面のアプリアイコンの下に表示される名前）を変えるため、ユーザー定義のビルド設定 `DISPLAY_NAME` を追加する。
Build Settings上部の + ボタンから `Add User-Defined Setting` を選択して設定を追加し、Setting名を `DISPLAY_NAME`、値をアプリの表示名にする。

![スクリーンショット 2018-03-29 10.56.35.png](https://qiita-image-store.s3.amazonaws.com/0/233769/69763bef-17a0-cc6b-b10c-b89ffdb117f3.png)

![スクリーンショット 2018-03-29 11.01.10.png](https://qiita-image-store.s3.amazonaws.com/0/233769/0e99998c-c572-b92b-1b9e-30088441f0f4.png)


## Info.plistの設定

Info.plistに `Bundle display name` の設定を追加し、Valueを `$(DISPLAY_NAME)` にする。
これで各TARGETのBuild Settingsに設定した、`DISPLAY_NAME` がアプリの表示名として適用される。

![スクリーンショット 2018-03-29 11.05.07.png](https://qiita-image-store.s3.amazonaws.com/0/233769/ece53b72-1197-afc4-33c9-1b52b43b874c.png)

同じ要領でUser-Definedの変数を追加すれば、Info.plistの他の値も、TARGETによって切り替えることができる。

## プログラム内での処理分岐方法

設定した`Other Swift Flags`によってプログラム内の処理を分岐させることができる。
`#if`、`#elseif`、`#else`、`#endif`を使って以下のように処理を切り替える。

主に参照するAPI、リソースなどを切り替える際に使用する。

```Swift:例
class Environment {
    var apiURL: String
    init() {
        #if PRODUCT
            apiURL = "https://api-prod.net"
        #elseif TEST
            apiURL = "https://api-test.net"
        #else
            apiURL = "https://api-else.net"
        #endif
    }
}
```

## TARGETを複数運用する際の注意点

複数TARGETを作った場合、ファイルを追加する際に全てのTargetsにチェックを入れるよう注意する必要がある。
チェックを入れないと、TARGETにリソースが含まれなくなってしまう。

![スクリーンショット 2018-03-29 11.30.51.png](https://qiita-image-store.s3.amazonaws.com/0/233769/907b8a1a-9145-5f92-dce8-95b21f454c81.png)

チェックを入れ忘れた場合、該当のファイルを選択して右パネルの ` Target Membership` からチェックを付けなおすこともできる。

![スクリーンショット 2018-03-29 12.12.43.png](https://qiita-image-store.s3.amazonaws.com/0/233769/f82c874d-8f05-a5cc-0f4b-ea073269e954.png)

Target毎に含まれるリソースが異なっている場合、`Build Phases`の `Compile Sources`、`Copy Bundle Resources` に表示されるitem数がTargetによって差がある状態になる。

![スクリーンショット 2018-03-29 11.36.32.png](https://qiita-image-store.s3.amazonaws.com/0/233769/4b12128d-5e9e-4ea0-e715-4272deda06df.png)

## Schemeの設定
各TARGETが設定できたら、起動のためのSchemeを作成する。
Xcode左上のScheme名のところから`Manage Schemes` を選択して、Schemeの一覧を表示。

![スクリーンショット 2018-03-29 11.39.21.png](https://qiita-image-store.s3.amazonaws.com/0/233769/c35cd258-2d05-6b3a-e675-c8d272af5ec4.png)

既存のSchemeを一度全て削除して、+ ボタンから任意のTARGET用のSchemeを追加する。
![スクリーンショット 2018-03-29 11.42.43.png](https://qiita-image-store.s3.amazonaws.com/0/233769/bc010abb-6980-8a62-6004-d2e0f55ce360.png)

以降は作成したSchemeを用いてアプリを起動すれば、Schemeに選択されたTARGETが適用された状態でアプリがビルドされる。

Schemeの設定はユーザーディレクトリに保存されるが、通常ユーザーディレクトリはgitignoreに設定してGit管理外とするので、Schemeの設定は各自で行う必要がある。

## Objective-C での設定方法

Objective-Cの場合、Build Settingsの`Other Swift Flags`の代わりに、`Preprocessor Macros`を使用する。
`Preprocessor Macros` に`TEST=1`などの値を設定することで、以下のようにプリプロセッサーマクロで処理を切り替えられる。

```Objective-C
#ifdef PRODUCT
    apiURL = @"https://api-prod.net";
#endif
#ifdef TEST
    apiURL = @"https://api-test.net";
#endif
```