FlutterアプリをiOS版ビルドに必要な手順のまとめ(debug/release)とTestFlightに上げるまで

FlutterアプリのiOS版をビルドするのに必要な手順をまとめます。
debugビルドと、releaseビルドの両方を載せます。releaseビルドは、TestFlightに上げるまでの手順です。

なお、個人開発者として登録する方法となっています。
組織の場合は必要な手順が異なりますので、以下のサイトなどを参考にして下さい。
https://dev.classmethod.jp/articles/ios-app-how-to-release-2018/

# 環境など

まず、リリースビルドをアップロードする際、iOS13に対応しないと行けません。
iOS13に対応するには、Xcodeが11.0以上でなければなりません。

これはMacOSをCatlinaに上げなきゃダメか・・・と思っていましたが！

MacOS Mojave(10.14.6)で動かせるのはXcode10.2までだと思ってましたが、以下によれば、Xcode11.3.1まで使えるようでした！

https://en.wikipedia.org/wiki/Xcode#Version_comparison_table

なので、まずXcodeを11.3.1アップデートし、Flutterも最新版(Stable)・・・といいたいところですが、17.0は出たばかりでちょっと怖いので、v1.12.13+hotfix.9に更新しました。

Xcodeの古いバージョンはこちらからダウンロード可能です。
https://developer.apple.com/download/more/

Command Line Toolsもお忘れなく。
そしてCommand Line Toolsをインストールしたらライセンス同意が必要なので`sudo xcodebuild -license`もお忘れなく。

|ツールなど|バージョンなど|
|:--|:--|
| MacBook Air Early2015|macOS Mojave 10.14.6|
|Android Studio |3.6.1|
|Java |1.8.0_131|
|Flutter|1.12.13+hotfix.9|
|Dart |2.7.2|
|Xcode |11.3.1|

# デバッグ実行するなのに必要な手順

Flutterアプリを、XcodeやAndroidStudio等から実機でデバッグ実行するために必要な手順です。なお、このセクションの内容は、数年前から非課金で行えるようになっています。(昔は実機デバッグをするにはデベロッパー登録/有料が必要でした)

## 1.開発者用Appleアカウントの作成
後でやるデベロッパー登録のことを考えると、この時点で、開発専用のAppleアカウントを作ってやった方が良いようです。そして登録内容は、すべて英語にするのが良さそうです。

私はiPadやMacを買ったときのアカウントでやってしまい、住所や氏名登録が日本語な為、本人確認に免許証などの公的に住所を証明する書類のアップロードを要求されました。
(pendingのまま審査が数ヶ月進まなかったため問い合わせてやっと理由が分かりました)


## 2.iOS Developer用の証明書の作成
Xcodeから生成出来ます。
これは初めてアカウントを作る場合の手順です。一度でも作成済みの場合は、作成済みのチームを選ぶだけでビルド、デバッグ実行が出来ます。

### (1)XcodeでFlutterプロジェクトを開く
`Flutterプロジェクトルート/ios/Runner`をXcodeで開きます。

### (2)targetsの`Runner`を選ぶ

- プロジェクトルートの`Runner`をクリック赤枠の箇所をクリックして`targets/Runner`を選ぶ
 
|![xcode_runner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/a012e8b4-749b-5161-0e03-30701c17a0dc.png)|
|:--|

|![xcode_select_target_runner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/56ddf0c4-89ab-c127-8a2c-6d70789d860e.png)|
|:--|

### (3)Sigining設定をする

- [General]タブの**Signing**項目の[Auto sigining]にチェックを入れる
- **Team**のドロップダウンをクリックする

|![xcode_debug_sigining.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/14428245-d190-2dcb-e033-619e3ed30cb5.png)|
|:--|

- [Add Account]を選ぶ

![xcode_add_account.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/8618534c-2c92-58a8-6ad7-c6ba718539b2.png)

- **Accounts**アプリが開くので、Apple IDでログインする
  - この時、開発用のアカウントを作っていれば、そちらを追加してログインして下さい。
- ログイン後、[Manage Certificates...]をクリック

![xcode_manage_certs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/799cb146-f533-bf43-32f6-466ab6bb9fb9.png)

- 左下の[+]アイコンをクリックして、**iOS Development**を選ぶ

![xcode_manage_certs_for_iosdev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/e3bc714e-57dc-e7cc-d326-1cc9d82ed172.png)

- [Download Manual Profiles]をクリック
- **Accounts**を閉じてXcodeに戻る
- **Team**のドロップダウンで今作成したチームが増えているので、それを選ぶ

|![xcode_select_team.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/3c6af167-7077-68cd-b557-622461e880bb.png)|
|:--|

これでデバッグビルド・実行が出来るようになりました。

## 3.Debugビルド用にBundle Idやアプリ名を変える

[Androidでやったように](https://qiita.com/kasa_le/items/d23075d817f42e869778)、iOS版も、debugビルドのBundle Idを変えて、releaseビルドとdebugビルドが同時にインストールできるようにします。

### (1)Bundle Idを変える
正式には、**Bundle Identifier**です。
Xcodeでは、[Targets]-[Runner]-[General]タブにあります。

|![xcode_build_id.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/87c4b565-ba43-467f-83ea-075dceca4b20.png)|
|:--|


ただ、Debug版とRelease版で切り替えるには、まず、**User Defined Setting**を追加する必要があります。

- [Project]-[Runner]を選ぶ

|![xcode_project_runner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/cc417590-2f5b-93af-dff3-bab71e90a220.png)|
|:--|

- [Build Settings]タブで、[+]-[Add User-Defined Setting]をクリック

|![add_user_defined_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/59704e13-255a-8d55-9b44-ebdd267df4d0.png)|
|:--|

- `BUNDLE_ID_SUFFIX`と入力する
- **Debug**に`.debug`と入力する

|![bundle_id_suffix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/3daea092-821e-69f2-73b3-b6826c6eed25.png)|
|:--|

- [Tragets]-[Runner]を選び、**Packaging**を探す

|![xcode_packaging.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/aef5cfd2-563c-e253-86e1-22b00de7a399.png)|
|:--|

- **Product Bundle Identifier**の項目の箇所をダブルクリックし、`${BUNDLE_ID_SUFFIX}`を末尾に追加する

|![add_suffix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/5ac3bb80-4d98-0ffc-4bf9-4b4bc3ede363.png)|
|:--|

### (2)Debugビルドのアプリ表示名を変える

DebugビルドとReleaseビルドが同時にインストールできるようになると、ホーム画面でどっちがどっちか分かりづらくなるので、一番簡単な「アプリ表示名」(Bundle Name)を変えて分かりやすくします。

- [Project]-[Runner]-[Build Settings]タブで、**Add User-Defined Settings**し、`PRODUCT_NAME_PREFIX`というのを追加し、Debugビルド版のみ`(d)`とする

|![product_name_prefix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/c159a16d-c3d0-cee7-4680-de4d6b3e6308.png)|
|:--|

- [Targets]-[Runner]-[Info]タブで、**Custom iOS Target Properites**の**Bundle name**を探し、`${PRODUCT_NAME_PREFIX}アプリ表示名`とする

|![bundle_name.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/d37fe21b-50f8-0b41-d71d-44b64fc13cb6.png)|
|:--|

これで、debugビルドのアプリが分かりやすくなりました。

### (3)GoogleService-Info.plist

上記のようにBundleIdを変えると、厄介なのがFirebaseを使うときに配置しておかなければならない`GoogleService-Info.plist`ファイルです。

これは、デバッグ用/リリース用それぞれの`GoogleService-Info.plist`ファイルをダウンロードして、`-Release.plist`, `-Debug.plist`などとリネームして配置しておき、**Build Phase**にスクリプトを作って、ビルドコンフィグに合わせてコピーして使う、という手段を取ります。

※Androidは、debug用もrelease用も全く同じファイルがDLされてくるので、恐らく以前のように`main`/`debug`などに分けて置いておく必要も無くなっているようで、より簡単です。

まず、`ios/Runner/Configs`などのフォルダを作って、それぞれのplistを保存します。

|![ios_configs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/35888a80-9dd1-efe5-7d78-6cadb6b159cd.png)|
|:--|

Xcodeで`ios/Runner`を開き、[target]-[Runner]の[Build Phase]を表示します。

**Run script**を探し、開きます。
無ければ、左上の[+]ボタンから、[New Run Script Phase]してください。

shellに、以下のように記入します。

```sh
if [ "${CONFIGURATION}" == "Release" ]; then
  cp "${PROJECT_DIR}/${PROJECT_NAME}/Configs/GoogleService-Info-release.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
else
  cp "${PROJECT_DIR}/${PROJECT_NAME}/Configs/GoogleService-Info-debug.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
fi
```

![ios_run_script.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/1489d570-7bd3-64e6-fbc0-eb6cffcfbda0.png)

これで、デバッグ実行とリリース実行のそれぞれに対応する`GoogleService-Info.plist`を使うことが出来るようになりました。



# リリースビルドしてApp Store Connectにアップロードするまでの手順

## 1.デベロッパー登録

Apple Developer ProgramへのEnrollが必要です。
日本語ページから行けますが、登録ページは英語のみです。

https://developer.apple.com/jp/programs/enroll/

前述の通り、アカウントは開発専用アカウントを作ってやった方が良いようです。

登録をすると、Apple様への$99/年のお布施が必要になります。

※Googleさんは登録時に1回こっきりの請求なので、敷居が低くて良いんだけどなー。まあ敷居が低いからこそ私みたいに払ってから10年も何もリリースしてないようなのも発生してしまうんでしょうが^^;


## 2.リリースビルドするまでの手順

### (1)iOS Distribution用の証明書の作成

- メニューの[Xcode]-[Prefernce]から、[Accounts]タブを表示する
- [Manage Certificats...]をクリック
- debug用の[iOS Developer用の証明書の作成](#2ios-developer用の証明書の作成)でやったのと同じ手順で、今度は**iOS Distribution**を選んで追加する

![xcode_ios_distribution.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/15698095-3ac7-e967-4589-e640183083a3.png)

- [Done]をクリック
- [Download Manual Profiles]をクリック

### (2)flutterコマンドでリリースビルド準備をする

コマンドラインで以下を実行する。
なお、事前にcleanはやっておいた方が望ましい模様です。

```console
$ flutter clean
$ flutter build ios
```

プロジェクトルートで実行して下さい。

### (3)XcodeでArchiveビルドする

- Xcodeのメニューの[Product]-[Archive]をクリックする
- しばらく待つと、ビルドが完了します。以下のような[Archives]画面が開くので、**Identifier**などが正しいことを確認します。

![xcode_archives.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/1a799334-c95c-4204-793b-7139c17d0ae3.png)

## 3.App Store Connectでアプリ情報を登録する

### (1)App Store Connectページへ行く
https://appstoreconnect.apple.com/

最初のアクセスの場合は、利用許諾ページが表示されるので、良く読んで同意します。

### (2)アプリを登録する

- **マイApp**をクリック
- 左上の[+]-[新規App]をクリックして追加ページを開く
- 必要な情報を入力し、保存する
  - **SKU**の項目は、特に管理方針などが無ければ、Bundle Identifierと同じで良いかと思います。

## 4.アプリケーションファイルをアップロードする

先ほど、Xcodeでアプリケーションファイルを作りました。
最後に表示されたページに、[Distribute App]というボタンがあったと思います。
※もし、ページを消してしまっていた場合は、Xcodeのメニュー[Window]-[Organizer]から開けます。

なお、これらの操作中、Macがとても重くなります(MacBook Airの場合)。あまり他の作業はしない方が吉かと思います。

- [Distribute App]をクリック
- Uploadを選択して[Next]をクリック
  - 初めての場合、表示されない場合もあるかも
- 必要があればオプションを選択し、[Next]をクリック
- [Automatically manage signing]を選択して[Next]をクリック
- **Review Runner.ipa content**が表示されたら、内容を確認して、[Upload]をクリック

アップロードが完了したら30分ほどでメールが来るようなので、他のことをして待ちましょう。

これで、アプリケーションファイルは出来ました。
これをテスト用に配信するために、TestFlightというのを利用します。

# TestFlightで配布する

TestFlightについては、以下などをご参照下さい。
https://developer.apple.com/jp/testflight/

要するに、リリース前のアプリをテスターに配信できる公式のツールと思って下さい。
今回は、外部テスターに公開することにします。

## 1.プライバシーポリシーページを作る

必須みたいです。(GoogleのPlayストアは、有料だったり13歳未満向けでなければ不要でしたが)
そもそもFirebaseAnalytics入れたので必要ですね。例えGoogleでも。
ということで、[こちらの記事](https://qiita.com/kasa_le/items/db9399184c92608a7fea)でFirebase Hostingを使ってプライバシーポリシーページを作りましたのでご参考下さい。

## 2.テスト情報ページの入力

App Store Connectでアプリを選び、[TestFlight]のタブをクリックすると、左側のメニューの下の方に、**テスト情報**というのがあると思います。
注意アイコンが付いていると思いますが、最低限、以下の内容を設定すれば消えます。

- ベータ版Appの説明
- フィードバックメールアドレス
- プライバシーポリシーURL
- ベータ版App Review情報の連絡先情報(全部)

サインインが必要なアプリの場合は、Appleさんがレビューするときに使えるアカウントを作っておいて、そのアカウント情報を設定する必要があります。
特にサインインなどないアプリなら、[ サインインが必要です]のチェックを外しておきましょう。

それと、[App Store]タブの**App情報**ページにもプライバシーポリシーページURLを設定する箇所があります。忘れずに入力しておきましょう。


## 3.輸出コンプライアンスの設定をする

[TestFlight]タブで、左側のメニューの[iOS]を選ぶと、アップロードしたアプリのバージョンなどが見られますが、[輸出コンプライアンスがありません]となっていてまたまた警告アイコンが出ています。

このままでは配信を開始できないので、そこをクリックし、[輸出コンプライアンス情報を提出]をクリックします。

以降は、以下のサイトなどを参考に、ご自分のアプリに即した回答をして下さい。
https://qiita.com/osamu1203/items/35df25d93e9d12b11222
https://www.ateliee.com/archives/3363
https://www.webbanana.org/goroku/2019/06/12/374.php

最後に[内部テストを開始]をクリックします。

これで準備が出来ました。
なお、これでアプリの審査が始まります。本配信よりは簡略化されたレビューだとは思いますが、一応されるそうです。

## 4.テスターの登録

今回は外部テスターを使いたいので、[外部テスターを追加]をクリックし、グループを作成します。グループ名は任意です。

### (1)テスターの登録
- 上記で作成したグループを選び、[テスター]タブを表示
- 配布したい人のメールアドレスを登録する

### (2)ビルドの設定
- [ビルド]タブに切り替える
- ビルドを選び、[追加]をクリック

審査が終わって配信可能になるのを待ちましょう。
配信可能になると、テスターに登録したメールアドレスへ通知が行くようです。

※世界的に新型コロナ対策期間中でした。審査通るのには3日ほどかかりました。これが通常なのかどうかは不明です。

### (3)テスト用アプリの更新をするとき

以下の手順を毎回行う必要があります。

[2.(2)flutterコマンドでリリースビルド準備をする](#2flutterコマンドでリリースビルド準備をする)
[2.(3)XcodeでArchiveビルドする](#3XcodeでArchiveビルドする)
[3.(4)アプリケーションファイルをアップロードする](#4アプリケーションファイルをアップロードする)
[3.輸出コンプライアンスの設定をする](#3輸出コンプライアンスの設定をする)
[4.(2)ビルドの設定](#2ビルドの設定)

そして、提出の度に審査があります。2回目からは比較的早いとは聞いていますが・・・

# 参考サイト

Flutter公式の手順解説
https://flutter.dev/docs/deployment/ios

Bundle Identifierをdebug版で切り替える方法などの参考にしました。
https://qiita.com/Todate/items/a2e6a26731c79bd23e02

表示名をdebug版で切り替える方法などの参考にしました。
https://medium.com/swift2go/different-app-display-name-based-on-xcode-scheme-d709307d0c01

ステップなどの概要確認に参考になりました。
https://dev.classmethod.jp/articles/ios-release-build-2015-11/
https://dev.classmethod.jp/articles/ios-app-how-to-release-2018/

XCodeでのAutomatic Signingについて参考になりました。
https://qiita.com/nerd0geek1/items/0b36c68897ee87e0a0c6

Testflight登録時のテスト情報の必須項目について参考になりました。
https://dev.classmethod.jp/articles/how-to-distribute-app-with-testflight-public-link/

GoogleService-Info.plistの切替について参考になりました。
https://medium.com/flutter-jp/flavor-b952f2d05b5d
https://qiita.com/ko2ic/items/53f97bb7c28632268b5a