【iOS】FlutterでFlavorを使って環境ごとに切り替えてビルドする(debug/stg/prod) 

>2019/11/28 13:12
>AndroidのFlavorと合わせるために一部Flavor名を修正しました(Debug→Develop)[
>その他、細かい修正
 

プロダクトで開発をしていると、検証等で環境ごとにビルドしたくなる事があると思います。

今回は Flutter の flavor というオプションを使って、

- Develop → 開発環境(Debug ビルド)
- Staging → ステージング環境(Debug ビルド, Release ビルド)
- Production → 本番環境(Release ビルド)

の 3 つの環境(ビルド構成は 4 つ)に分けてビルドする方法をまとめていきます。

## 下準備
### 環境構築

※Flutter の環境構築がまだだよって方が[こちらをどうぞ](https://flutter.dev/docs/get-started/install)

Flutter の Stable チャンネルを利用してます。
※ 2019/11/28 現在で 1.9.1+hotfix.6

チャンネル切り替えは *`flutter channel`*でできます。

```bash

$ flutter channel stable

```

``flutter --version``を実行してみて以下と同じ感じになれば OK です！

```bash

$ flutter --version
Flutter 1.9.1+hotfix.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 68587a0916 (2 months ago) • 2019-09-13 19:46:58 -0700
Engine • revision b863200c37
Tools • Dart 2.5.0
```

※ もし実行時の Stable チャンネルではうまく行かないよという場合は *`flutter version`*で version を指定できるので試してみてください。


### プロジェクト生成
*`flutter create`*で Flutter プロジェクトを生成します。

```bash
$ flutter create \
​    --org me.skycat.example.flutter.env \
​    --with-driver-test \
​    flutter_env_build
```
※IDE で FlutterProject を作成しても OK です

プロジェクトが完成したら```flutter run``してみて、初期のカウンターアプリが動くか確認しましょう！

## iOS で各環境のビルド構成を設定する
Xcode 上で各環境の Schema を作り、xcconfig で各環境ごとにビルド設定をしましょう。

### Xcode プロジェクトを編集する
プロジェクト直下の ios ディレクトリ内の``Runner.xcodepro``を開いて編集してください。(``ios/Runner.xcodeproj``)

デフォルトのビルド環境は以下の画像ように、Debug/Release/Profle の 3 つのビルド構成があり、
Debug は Debug.xcconfig、Release と Profile は Release.xcconfig が設定されています。
<img width="707" alt="image-20191127222943687.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/b07a3eab-3d9b-1772-3cfc-cd071975eed3.png">

#### 必要なビルド構成を追加する

今回は 以下の４つの構成を作ります。

- Debug-Develop
  - DevelopのDebugビルド構成
- Debug-Staging
  - StagingのDebugビルド構成
- Release-Staging
  - StagingのReleaseビルド構成
- Release-Production 
  - ProductionのReleaseビルド構成

``[+]``を押して、すでにある構成をコピーして作りましょう。
``Duplicate "Release" Configuration``をクリックして作ります。
作成後はダブルクリックで名前を変更できるので適切な名前に変更してください。

<img width="722" alt="image-20191127231910372.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/ecee1df4-b3b1-08a7-a796-e00632e3675b.png">

追加が終わったら、不要な Release/Profle を消しましょう！
以下の画像のようになっていたら完璧です。
<img width="737" alt="image-20191128124250258.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/5740485b-edde-1189-5524-62bd22659b8f.png">

#### それぞれの環境用のビルド設定(xcconfig)を追加する
ビルド構成ごとに xcconfig を用意しましょう。
プロジェクト直下の ios/Flutter に以下のファイルを追加してください。

###### Develop.xcconfig

```Develop.xcconfig
#include "Generated.xcconfig"
TRACK_WIDGET_CREATION=

FLUTTER_FLAVOR=Develop
PRODUCT_BUNDLE_IDENTIFIER=me.skycat.example.flutter.env.dev
DISPLAY_NAME=SAMPLE-dev
```

##### Staging.xcconfig
```Staging.xcconfig
#include "Generated.xcconfig"
TRACK_WIDGET_CREATION=

FLUTTER_FLAVOR=Staging
PRODUCT_BUNDLE_IDENTIFIER=me.skycat.example.flutter.env.stg
DISPLAY_NAME=SAMPLE-stg
```

##### Production.xcconfig
```Production.xcconfig
#include "Generated.xcconfig"
TRACK_WIDGET_CREATION=

FLUTTER_FLAVOR=Production
PRODUCT_BUNDLE_IDENTIFIER=me.skycat.example.flutter.env.prod
DISPLAY_NAME=SAMPLE-prod
```
追加したものをビルド構成に設定していきます。
<img width="873" alt="image-20191128124620846.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/fcb496ae-6044-4406-a5fa-2d9d1cb22a8f.png">
※ 選択肢に追加したものが出てきていない場合は、Xcode に認識されないので[再追加の必要](https://qiita.com/skycat_me/items/76423e1c534088a62f7f)があります。


#### ビルド設定(xcconfig)に設定した変数を適用
xcconfig で設定した変数を適用させるためにプロジェクトの設定を変更する必要があります。

アプリの表示名(DISPLAY_NAME)を適用させるために、
``info.plist``に``CFBundleDisplayName``を``$(DISPLAY_NAME)``として定義してください。

```
​    <key>CFBundleDisplayName</key>
​    <string>$(DISPLAY_NAME)</string>
```
<img width="580" alt="image-20191128013615851.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/eacc12be-7deb-ce71-3474-3cf2bfc9378f.png">

そして BundleID が反映されるように、
TARGETS->Runner->BuildSettings の ``Product Bundle Identifier`` を削除(フォーカスした状態でDeleteKeyでOK)して、
info.plistのCFBundleIdentifier(.xcconfigで設定しているPRODUCT_BUNDLE_IDENTIFIER)を読み込むようにします。
<img width="873" alt="image-20191128124620846.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/b131660f-1c8b-192b-286b-2e7b34764c7a.png">


#### Flavor に対応した Schema を追加
Flutter の flavor オプションからビルド構成を選択するために Schema を 3 つ追加します。

``Product > Schema > Edit Schema``
<img width="542" alt="image-20191128001653270.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/58d89f40-2dd4-2b17-2448-a9a81884e376.png">

``Ducplicate Schema``をクリックするとコピーとして作られるので、Schema 名をビルド構成と同じ名前に設定します。
<img width="875" alt="image-20191128001825268.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/9b6ea470-d647-9457-4bcb-45915087c27f.png">


そして``Runのinfoタブ``を開いて、``Build Configuration``に Schema 名と同じビルド構成を選択してください。

``StagingとProductionは*Debug executable*のチェックを外してください``
(Debug表示がなくなってログが吐かれなくなります、必要な人は外さなくてもいいです)

↓ の画像は Develop の例
<img width="724" alt="image-20191128130850245.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/4b822954-570c-aeba-a980-67979c18ec6d.png">

ReleaseビルドのあるStagingとProductionは ``Profile``と``Archives``も*`Build Configuration`*設定してください。
``StagingはRelease-Staging``、``ProductionはRelease-Production``になります、

Develop/Staging/Production の 3 つ分が作り終わるとこんな感じになります。

*`Product > Schema > Manage Schemes...`*
<img width="741" alt="image-20191128003449536.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/4b1fa7df-e591-d7d8-2923-52fee85fdb34.png">

これでビルドの準備ができました！
Flavor を指定してビルドしてみましょう！

Flavor が Staging(flutter run --flavor Develop)だと

```
表示名が SAMPLE-dev
BundleIDが me.skycat.example.flutter.env.dev
```

Flavor が Staging(flutter run --flavor Staging)だと

```
表示名が SAMPLE-stg
BundleIDが me.skycat.example.flutter.env.stg
```
なアプリがインストールされます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24241/fe913e98-4495-2a23-8167-f47f7370ee27.png)
これで iOS の Flavor 設定はおわりです！


*`※ 注意 ※`*
Production は Debug モードの設定いれていないので、Simulation では実行できません！
（本番環境を Simulation で見ることなんてないやろという考え）

## おわりに
「うまくいかない」とか「ここってどうなの？」みたいなことがあったらコメントお願いします 🙏
Android はまた別記事で書きます〜。

そのあとくらいに、

- いろんな CI(Codemagic, Github Actions, Bitrise...etc)での設定

- Flavor での各種切り替え(Firebase プロジェクト, ランチャーアイコン, API の向き先)

などなどの記事も書いていきます〜。よろしくおねがいします🙏