CrowdWorksのiOSアプリ開発環境を晒してみる

# はじめに

この記事は[CrowdWorks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/crowdworks) 4日目の記事です。

[CrowdWorksのiOSアプリ](https://itunes.apple.com/jp/app/kuraudowakusu-furiransu-fu/id1013797155?mt=8)は2015年の7月に初版としてメッセージアプリとしてリリースされ、いったんの開発中断を挟みながらも、2016年5月に検索機能を追加して12月現在もエンハンスを続けています。

![2b1c0f1d-767e-5145-af24-44e2312de760.png](https://qiita-image-store.s3.amazonaws.com/0/39009/2e9db16f-b6b9-693f-79d2-ecabbd7555bd.png)


アプリを作っていると他の会社ではどう開発しているんだろう、ということがよく疑問に思ったりもするので、一つの事例としてご紹介できればと思います。

# Xcodeプロジェクト構成

## Swift 3, Xcode 8

アプリはほぼすべてSwiftにて実装しており、Swift 3, Xcode 8に対応しています。
iOS Development Targetは9.0にしてiOS 9.0以降をサポートしており、なるべく古いバージョンは切り捨てながら新しいバージョンに追随するようにしています。

## ReactiveCocoa

開発をはじめた2015年春くらいには、iOSでもリアクティブプログラミングをしてみるのが流行りだしていた頃でしたので、CrowdWorksアプリでも[ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa)ライブラリを取り入れ、実装もMVVMで実装しました。

ちなみに、当時のReactiveCocoaはまだversion 2.5で、Objective-Cによる実装でした。（現在はなんともうすでに5.x系の開発が進んでいる模様です）
アプリはSwiftで実装していたため若干無理をして使っているところもあるのですが、現在もまだバージョン2.5を使っておりSwift対応の新しいバージョンに移行したいところです。

## Realm

実際にはまだプロダクションのアプリにはのっていないのですが、アプリ内部のDBとして[Realm](https://realm.io/jp/)を利用するように対応中です。
RealmはCoreDataを使うよりも高速に動作するのと、データの変更に対してリアクティブに実装することが簡単にできるので、どんどん使っていきたいライブラリとなっています。

## グループ構成

<img width="304" alt="d2ec0770-17cf-77ee-53af-6cb5ab289d02.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/e904402d-6d69-7106-69ee-bf3e7441ec11.png">


今でもどう分けるのが正解なのかも分かっていないですが、現状こんな感じで落ち着いています。
MVVMにおけるVMに相当する```ViewModels```グループと、Vに相当する```View```, ```ViewControllers```グループ、Mに相当する```Managers```や```Services```などに分かれています。

グループ | 内容
---- | ----
cw-ios/Utils | 共通的な処理など
cw-ios/Resources | 画像やフォントファイルなど
cw-ios/Views | UIViewやUITableViewCellのサブクラスなど
cw-ios/ViewModels |ViewModelクラス
cw-ios/Services | サービスクラス
cw-ios/Managers | 保存データの管理を行ったりするクラス
cw-ios/Entities | Web API通信の結果や保存するデータのエンティティを定義するクラス
cw-ios/Supporting Files| Info.plistやBridging-Header, entitlementsなど諸々突っ込んでいます。
Frameworks | 導入したframeworkをまとめています。
Libraries | CocoaPodsで管理していないサードパーティ製のライブラリ
cw-iosTests | テスト関係
Products | ビルド生成物など
Pods | CocoaPodsが自動で生成したxcconfingファイル

## ディレクトリ構成

<img width="400" alt="4acfa1a2-a8aa-21d2-01d0-4671791786ad.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/0486b08d-283e-4f68-e4bf-814f8f983492.png">


Xcode上のグループ構成と違って、実際のファイルシステム上のディレクトリ構成は実装したソースコードはフラットに配置しています。
こうしないとXcode上でグループ構成をいじったりするに従い、ディレクトリ構成との乖離が発生してきて結局ぐちゃぐちゃになっていくようになるからです。

基本的に開発したソースコードはすべてcw-iosディレクトリに入っており、サードパーティ製ライブラリなどはlibrariesディレクトリに分けたりしています。
これは、今後自分達で開発したボリュームがどのくらいだったのかの把握がしやすいかなと思って分けています。

## CocoaPods

サードパーティライブラリの管理には[CocoaPods](https://guides.cocoapods.org/)を利用しています。
[CocoaPodsで推奨している](https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control)ように、```pod install```して得られたライブラリなどはすべてGitへコミットするようにしています。

> Whether or not you check in your Pods folder is up to you, as workflows vary from project to project. We recommend that you keep the Pods directory under source control, and don't add it to your .gitignore. But ultimately this decision is up to you:

ライブラリ提供元が公開内容を変更したりすると、過去バージョンのビルドが再現できなかったりするので、一緒にバージョン管理しておいたほうが良いと思います。

##　独自アイコンフォント

<img width="375" alt="f5f4ad63-24e5-328f-2f79-d5a5dd8ddce9.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/b55e17b6-e1ad-ec04-3026-1d85342d597b.png">


赤丸で囲んだところのように、お気に入りボタンを表示する必要が出てきたとき、画像ファイルを用意することが多いかと思われますが、CrowdWorksではアイコン表示用に独自フォントを作成しています。
表示するのは文字であるため、大きく表示しても綺麗に表示できるしサイズも軽く済んだりするので、よく利用しています。

また独自にアイコンフォントを作成するまでもなく、[Font Awesome](http://fontawesome.io/)にすでにある場合にはFont Awesomeのものを良く利用しています。


# 外部サービス

## Fabric

公開したアプリでクラッシュが発生していないかを計測するために、[FabricのCrashlyticsというサービス](https://get.fabric.io/)を利用しています。
Appleのクラッシュレポートだけだとアプリを公開したあとのクラッシュを把握するのは難しいので、こういったサービスを利用すると非常に役立ちます。
CrowdWorksでは直近7日間のクラッシュ率が0.3%以内になるよう意識しながら、監視を続けています。

<img width="1389" alt="78d3977f-718c-9229-32d7-31a1810e84b7.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/de9e2564-bce3-f6d8-7365-67000c5873fd.png">

また[FabricにはiOSアプリ](https://itunes.apple.com/us/app/fabric-real-time-app-analytics/id1077938720?mt=8)が提供されており、これをインストールしておくとクラッシュが急増した場合にはプッシュでお知らせしてくれるため、オススメです。

## Flurry

アクセス解析に利用しています。
ユーザーさんのアプリ上の行動について測定します。

## CircleCI + Fastlane + DeployGate

アプリのCIとして[CircleCI](https://circleci.com)を利用しています。

CrowdWorksアプリはGitHubのプライベートリポジトリで管理していますが、リポジトリにプッシュしたタイミングでCircleCIでフックしブランチ名によって様々な処理を行うようになっています。
処理内容は[Fastlane](https://github.com/fastlane/fastlane)で記述しています。

開発時のブランチの場合には、UnitTestやビルド番号をインクリメントしてGitHubにプッシュしたり、開発サーバーや本番サーバーと接続するようにしたアプリをAd Hocでアーカイブした結果を[DeployGate](https://deploygate.com/)で社内配布を行っています。

リリース時のブランチの場合にはさらにReleaseアーカイブしてApp Storeにアップロードしたり、dSYMをCrashlyticsにアップロードしたりしてクラッシュレポートのシンボル情報を解決（symbolicate）できるようにしています。

# ツール

特に利用頻度の高いツールを紹介します。
SketchもCharlesも有料のツールとなりますが、とても有用なため自腹を切ってでも購入したいツールとなっています。

## Sketch

<img width="1418" alt="a71dbbd5-f80c-6077-8961-d18c124af025.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/110e896a-f3d8-4ae8-c124-6685d07cc426.png">

iOSやAndroidアプリ開発で最近有名なデザインツールの「Sketch」を利用しています。
豊富なテンプレートや誰かが作った[Sketch APP RESOURCES](https://www.sketchappsources.com/)などからデザインリソースをダウンロードして取り込むことができたりするため、非デザイナーでも簡単にアプリのデザインに取り組むことができます。

## Charles

<img width="1421" alt="b3691468-63e0-49b7-3949-0b24e1e50571.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/e504b4fd-a58e-c36a-030b-fda7b5120ba6.png">

[Charles](https://www.charlesproxy.com/)はMac上にProxyをたてて、そこに流れるHTTP, SSL/HTTPS通信内容をみたりできるツールです。

アプリを実装していると、APIの通信結果をログに出力してコンソールを確認するよりも、Charlesの表示を確認する方が手軽なのとより確実に内容が把握できるため、このツールがあるとないとでは大分開発効率が違ってくるのではないかと思います。

# おわりに

この記事は[CrowdWorks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/crowdworks) 4日目の記事でした。

明日は[@YusukeIwaki](http://qiita.com/YusukeIwaki)のAndroidに関する記事の予定です。