個人アプリ開発を支える技術と開発フロー

iOS Advent Calendar 2018 の 10 日目です。

アプリをいくつかリリースしたり、ハッカソンでアプリを作ってきた中で個人的に定石となってきた開発フローや使っているツールなどをざっくりと時系列順で紹介します。

# 企画・アイデア

日頃から、何気なくアイデアを考えたりしています。「これ不便だな」と思ったら、どんなツールがあれば良くなるんだろうと考えてアプリのアイデアにしたり、Twitter などで面白い技術を使った動画を見つけたら、「これって他にも応用できないかな」と考えたりしています。

アイデアを考えているだけでは 3 日後には忘れてしまうので、メモをしておきます。
自分がよく使っているのは [Trello](https://trello.com/) と [Simplenote](https://simplenote.com/) です。

Trello でボードを作り、ジャンル (ユーティリティ、ゲームなど) ごとにリストを作って、アイデアのコア部分をカードにメモしています。
カードには詳細説明を書いたり、画像を添付したりすることもできるので、思いついたことを全部書いておきます。

Simplenote は雑にメモしたいときに結構便利で、Trello でカード化するほどまとまってなかったりするものはとりあえずここに書いておきます。
自分は主に Mac、 iPhone、iPad、 Windows を使っているので、今使ってる環境でメモをしてすぐに同期ができるのが快適です。(地味に Web で共有する機能や、バージョン管理機能があるのも役立ちます)

アプリのアイデア以外にも LT のネタや勉強会やカンファレンスのメモなどにも使っていてかなりごちゃごちゃですが、タグと全文検索機能があるので、なんとかなってます。
どーでも良いですが、この記事も Simplenote で書きました。(使い勝手は微妙ですがマークダウンもサポートされてます)
(無料のサービスであるのと、自分は数年使っていて起きたことがないですがデータが消えたというレビューを見たこともあるので、大切なことは書いてないです。)


ハッカソンのときは、マインドマップツール (XMind など) を使って無理矢理にアイデアを引き出したりもしてます。

#  デザイン
デザイナーさんにお願いできるときはお願いします。そのほうが絶対に良いものが出来ます。

自分でデザインをする必要があるときは [Sketch](https://www.sketchapp.com/) を使っています。
いろいろな人がテンプレートや UI を提供してくれているので利用します。

- [Apple Design Resources - Apple Developer](https://developer.apple.com/design/resources/)
- [【Sketch無料リソースの2018年決定版！】Sketch用UIキット、ワイヤーフレームキット55選【Sketchユーザーダウンロード必須！】 | WebDesignFacts](https://webdesignfacts.net/entry/sketch-wireframe-ui-kit-201805/)

Sketch で作るほどの気力がない時は iPad Pro と Apple Pencil でざっくりとしたデザインや画面のフローを考えたりもしています。
紙と鉛筆では書き直すのが大変ですが、iPad Pro ならボタンの位置を変えたり、画面のフローを整理するのも簡単です。

おすすめの iPad アプリ
- Procreate: 雑にスケッチするのに良い (可愛いキャラの絵を描きたくなるのがデメリット)
- Vectornator: UI パーツが用意されていたり、Icons 8 からアイコンを検索する機能があるのが良い
- Affinity Designer: (まだ使ってないのでわからないですがドロー系の中ではかなり良さそう)

なかなかしっくり来るデザインが思い浮かばないときは App Store でひたすらアプリを落として触ってみたり、[Pinterest](https://www.pinterest.jp/) や [Dribbble](https://dribbble.com/) で アプリ UI デザインを眺めたりしています。

ボタンアイコンなどの素材は [flaticon](https://www.flaticon.com/) や [icons8](https://icons8.com/) などから良いものを探したり、Unity でもアプリを作っているので [Unity Asset Store](https://assetstore.unity.com/) で購入した素材を使ったりもしています。

アプリのアイコンは Sketch なら簡単に必要なサイズを Export できますが、大きい画像 1 枚しかない時は [appiconmaker](http://appiconmaker.co) で自動でリサイズして生成したりしています。

# バックエンドの準備

iOS のアドベントカレンダーなので省略しますが、サーバレスにできるアプリならできるだけそうします。運用が面倒なので...
最近は [Firebase](https://firebase.google.com/?hl=ja) にほとんど頼っています。

# アプリ初期プロジェクトを利用する

ここからはアプリの開発的な話です。

すばやく開発をスタートするために良い方法は、いつも使うようなものを事前に入れておいた初期プロジェクトを作っておいて、それを clone して開発を始めるという方法です。
モチベーションが高い間に、すぐにコアの部分の開発に取り掛かれて良いです。また、ハッカソンでは時間短縮になります。

自分がよく使っている初期プロジェクトはこちらで公開していますので、使いたい方はどうぞ。

https://github.com/tattn/HackathonStarter


## よくある機能をコンポーネント化してすぐに利用できるようにする

課金、カメラ、カメラロールへのアクセス、プッシュ通知などコンポーネント化出来るよく使う機能は、一度作ったら切り出して使える状態にしておくと良いです。
もちろん、自分で作ったものだけでなく、公開されているライブラリなどを利用してもよいです。

自分はこのようなライブラリをよく使っています。

| ライブラリ | 機能 | メモ |
|:-:|:-:|:-:|
| [Alamofire](https://github.com/Alamofire/Alamofire) | 通信処理を簡単に扱える | |
| [Reachability.swift](https://github.com/ashleymills/Reachability.swift) | ネットワークに繋がっているかなどの判定を簡単に扱える | |
| [Result](https://github.com/antitypical/Result) | API のレスポンスなどのハンドリングがわかりやすくなる | 今後標準化されるため要らなくなる |
| [Kingfisher](https://github.com/onevcat/Kingfisher) | 画像フェッチライブラリ | [Nuke](https://github.com/kean/Nuke) もおすすめ |
| [SwiftGen](https://github.com/SwiftGen/SwiftGen) | リソースの定数などを自動生成してくれる | [R.Swift](https://github.com/mac-cain13/R.swift) もおすすめ |
| [LicensePlist](https://github.com/mono0926/LicensePlist) | ライブラリのライセンス表示を自動生成してくれる |
| [RxSwift](https://github.com/ReactiveX/RxSwift) | リアクティブプログラミングフレームワーク | |
| [SVProgressHUD](https://github.com/SVProgressHUD/SVProgressHUD) | 通信中のぐるぐる | |
| [KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess) | Keychain の操作が簡単にできる | |
| [SwiftDate](https://github.com/malcommac/SwiftDate) | 日付の操作が簡単にできる | |
| [SwiftyUserDefaults](https://github.com/radex/SwiftyUserDefaults) | UserDefaults を Swift らしく扱える | |
| [SwiftyStoreKit](https://github.com/bizz84/SwiftyStoreKit) | 課金実装を簡単に扱える | |
| [SwiftLocation](https://github.com/malcommac/SwiftLocation) | 位置情報を簡単に扱える | |
| [SwiftyXMLParser](https://github.com/yahoojapan/SwiftyXMLParser) | XMLを簡単に扱える | |
| [SwiftExtensions](https://github.com/tattn/SwiftExtensions) | Swift に便利な機能を追加できる | |
| [Realm](https://realm.io/jp/) | アプリ内データベース | |
| [Firebase](https://firebase.google.com/?hl=ja) | アナリティクスやプッシュ通知、データベース、クラッシュレポートなど | |


UI 系は [Cocoa Controls](https://www.cocoacontrols.com/) でアプリにあったものを探すのがおすすめです。

### ライブラリはラップして使う

ライブラリを使う際は出来るだけインターフェースを直接利用せず、ラップして使うようにしています。

```swift
import Kingfisher

extension UIImageView {
    func setImage(with url: URL) {
        kf.setImage(with: url)
    }
}
```

このようにすることで、ライブラリの更新でインターフェースが変わっても変更箇所を少なくでき、ライブラリを入れ替えることになった時にも簡単に差し替えができます。

# API のレスポンス用の型を簡単に用意する

JSON の API を利用する場合は Swift の Codable でレスポンスの型を作るのがオススメです。
自前で型を用意するのが面倒な時は JSON から型を自動生成してくれるツールを使います。

このツールがオススメです。
https://quicktype.io/

ブラウザで API を叩いて、結果をコピペするだけで型を作ってくれます。

# 多言語対応
作ったアプリをより多くの人に触ってもらうためには多言語対応はとても大事です。
iOS の場合は Localizable.string を使いますが、もし同様のデザインの Android 版 も作る場合は、一旦、[スプレッドシート](https://www.google.com/intl/ja_jp/sheets/about/) にまとめておくと、対応が楽になります。

また、googletranslate 関数や Google Apps Script の `LanguageApp` の機能を使うことで一括で多言語への機械翻訳も出来ます。
[Gengo](https://gengo.com/ja/) などの翻訳サービスを使う場合もエクセルの形式でエクスポートしたものをそのまま渡せたりするので便利です。

表を作る際はスクリプトで処理しやすそうなフォーマットを意識すると良いです。
そうすることで、iOS の Localizable.strings ファイルや Android の strings.xml をスクリプトで自動生成することもできるようになります。下記のサイトが参考になります。

[iOS と Androidで共通のローカライズファイルを作ろう！ (iOS Advent Calendar 2016) ｜ DevelopersIO](https://dev.classmethod.jp/smartphone/ios-android-common-localize/)

# Apple の審査を突破するための実装を入れる
アプリの本質的な機能が実装できたら、次は Apple の審査を突破するために必要な機能を実装します。
例えば、True Depth API を使う場合はプライバシーポリシーに収集したデータをどのように利用するかなどを記載する必要があったり、アプリ内課金がある場合は課金情報の復元 (Restore Purchase) 機能が必要だったりします。
UGC (ユーザー生成コンテンツ) がある場合は結構注意事項が多いです。

Apple が日本語でもガイドラインを提供しているので、読んでおくことが大切です。
[App Store Reviewガイドライン - Apple Developer](https://developer.apple.com/jp/app-store/review/guidelines/)

個人アプリでプライバシーポリシーを用意するのは大変ですが、プライバシーポリシーを生成してくれるサービスもいくつかあるので、自己責任ですが利用して、生成されたものを必要に応じて書き換えて使用するのも良いかもしれません。

[App Privacy Policy Generator](https://app-privacy-policy-generator.firebaseapp.com/)

プライバシーポリシーの公開場所に迷う場合はとりあえず、GitHub Pages に置いておくのが楽でおすすめです。

また、アプリ内にお問い合わせ機能も必要です。 (ガイドライン 1.5)
お問い合わせ機能には [Google Form](https://www.google.com/intl/ja_jp/forms/about/) がおすすめです。簡単に公開でき、URL パラメータで記入欄の自動入力をすることもできるので便利です。

# 今後必要になる情報を保存しておく

忘れがちですが、今後のアプリの更新で必要になるかもしれない情報を UserDefaults などに保存しておくと良いです。
例えば、初回起動日時、起動回数、最後に起動したアプリのバージョン、などです。
起動回数によって特別な画面を出したり、アプリ内に保存しているデータのマイグレーションが必要になった際の対応が楽になります。

# 申請準備

アプリの実装が終わったら、次は申請の準備です。

## プロファイルなどの設定

[Apple Developer ポータル](https://developer.apple.com/account/) で、公開用のアプリの AppID や Provisioning Profile を作成します。
最近は Xcode がいろいろと自動でやってくれますが、予期せぬ設定をされてしまうこともあるので、調べながら手動で設定したほうが良いかもしれません。


## ストア設定

[App Store Connect](https://appstoreconnect.apple.com) (以下、ASC) で公開に必要な情報を入力します。
大変ですが、多言語対応しておくと良いです。

ストア用のスクショは fastlane の [frameit](https://docs.fastlane.tools/actions/frameit/) で書き出すようにすると自動化出来て楽です。
こだわりたいときは Sketch などで作ります。

課金のテストをするためには、ASC でアプリ内課金の設定をする必要があります。値段や説明、審査用の画像 (スクショなど) を設定してアプリの審査よりも先に審査をしてもらいます。
一日くらいで承認済みになり、課金のテストができるようになります。

ASC 内のバージョンのリリースというセクションで「このバージョンを手動でリリースする」という設定項目があります。念の為、手動の方にチェックを入れておくと良いです。
手動にしておくと、アプリの審査が通った後に (時間差はありますが) 自分で公開タイミングを決めることができます。運良く公開前に自分でバグを見つけたときは、そのビルドの公開をキャンセルし、修正後のビルドで再度審査に出すことが出来ます。

## ビルドのアップロード

[fastlane](https://fastlane.tools/) でビルドのアップロードをできるようにするのをおすすめします。
一度設定をしてしまえば、今後のアップデート時にコマンド一つでアーカイブビルドやアップロードができるようになり非常に楽です。

ストア文言やスクショも fastlane で更新することが出来ます。最初は ASC 上で設定をし、その後 `$ fastlane deliver download_metadata` や `$ fastlane deliver download_screenshots` コマンドを実行し、設定をファイル化すると安全です。
生成されたファイルは Git にコミットしましょう。コミットしておくと何らかのミスで設定が消えてしまったり、過去の設定を見たくなった際に便利です。

## TestFlight

ビルドをアップロードすると [TestFlight](https://developer.apple.com/jp/testflight/) でアプリを配布できるようになります。パブリックリンクという機能を使うと簡単に自分以外の人がインストールできるリンクを作ることができるので関係者に配布してテストしてもらいましょう。

TestFlight ではテスト課金も可能なため、検証しておきましょう。

## 申請

テストが完了したら、ついに申請です。
最近は初回のアプリの審査の場合でも 1 日 〜 3 日で終わります。待ちましょう。

イベント用のアプリなどで公開期日が決まっている場合やアップデートしたアプリに致命的なバグが有る場合は、[特急申請 (Expedited App Review)](https://developer.apple.com/contact/app-store/?topic=expedite) をすることで優先的に審査をお願いすることも出来ます。
自分はまだ来たことがないですが、使いすぎると Apple から警告が来るようなので適切に判断をして利用しましょう。

### リジェクト

1 発で審査を突破するのはなかなか難しいです。初回はリジェクトされる覚悟で申請しましょう。

リジェクトされた場合は何らかの対応が必要です。
バグの場合は、手順やクラッシュログ、スクショなどが送られてくるのでそれを見て対応します。iPhone アプリなのに iPad でチェックされてクラッシュ報告が来ることもあるので、ユニバーサルアプリでなくても iPad でも動くような実装にしておいたほうが良いです。(ガイドラインの 2.4.1 項)

Apple のレビュアーも人間なので、アプリの挙動や UI を理解してもらえないこともあります (特に日本語のアプリの場合)。
その場合は 問題解決センター (Resolution Center) で返信をしてレビュアーと認識を合わせたり、App Review Board (App 審査委員会) に対して異議申し立てを [Contact](https://developer.apple.com//contact/app-store/?topic=appeal) からしたりします。
そこで解決できれば、ビルドの再アップロードなしに審査を通してもらえることもありました。
1 日 1 通くらいのやりとりになるのでできるだけわかりやすくメッセージを送るようにし、気長に待ちましょう。

## Bitrise + DeployGate

fastlane はローカル環境で実行してもよいのですが、公開したアプリを今後も継続的にアップデートしていきたい場合は、CI/CD 環境を整えておくと楽になります。

CI/CD 環境としては無料でお試しができ、綺麗な UI で機能が充実している [Bitrise](https://www.bitrise.io) がおすすめです。
また、テストビルドのデプロイ先としては [DeployGate](https://deploygate.com/?locale=ja) がおすすめです。TestFlight よりもすばやく配布ができるため、検証のサイクルを早く出来ます。

長く運用していくアプリの開発ではこのような部分の整備が品質や開発スピードの向上のために非常に大事になります。
1 年前の記事ですが、興味がある方は、こちらに書いた記事も読んでみてください。

[乗換案内アプリのCI/CDの取り組みについてのご紹介 - Yahoo! JAPAN Tech Blog](https://techblog.yahoo.co.jp/advent-calendar-2017/transit_ci_cd/)

# Slack に通知を集約

アプリの公開後はユーザーからどのような反応があったかをチェックしたいです。
いろいろな場所を見に行くのは大変なので Slack にできるだけ集約させています。
Google Apps Script を使ってアプリのレビューを流したり、お問い合わせメールを転送したり、Twitter のエゴサ結果を流したり、などいろいろ活用できます。

# まとめ

iOS アプリを公開するためには開発以外にもいろいろと作業が必要で大変ですが、アプリ開発ができてアイデアもある人は、趣味でのアプリリリースにチャレンジしてみてはどうでしょうか？
ダラダラとやっていると [エターナってしまう](https://dic.nicovideo.jp/a/%E3%82%A8%E3%82%BF%E3%83%BC%E3%83%8A%E3%82%8B) ので、期限を決めたりして短期決戦で臨むのがおすすめです。

また、個人アプリのメンテナンスは大変なので、メンテンナンスしやすい実装にしておくことも大事です。
この点に関しては Swift Advent Calendar 2018 に投稿した、[Better Swift](https://qiita.com/tattn/items/3b90bb01e9771ec27b00) に Tips が詰まっているので、興味がある方は見てください。

以上、iOS Advent Calendar 2018 の 10 日目でした。