QiitaクライアントのQolkをMacbookとCarthageで作った話


![Qolk_land.png](https://qiita-image-store.s3.amazonaws.com/0/24041/54c626c7-9723-52e4-b91e-eaf5025c5fb6.png "Qolk_land.png")

- [Qolk - AppStore](https://itunes.apple.com/jp/app/qolk-for-qiita-cozy-qiita/id1042929986?l=ja&ls=1&mt=8)

Qiitaの[公開API](https://qiita.com/api/v2/docs)を使ってアプリを作ってみました。目指したのは、「普通のアプリ」です。奇をてらったことをせず、自然に気持ち良くiPhoneで読めたらいいなと思って作りました。

実はもう一つ理由があって、Swift発表から1年以上経ち、だいぶ新しいライブラリが充実してきています。そういう新しいライブラリを使ってみたいというのもありました。

**Cocoapodsを一切使わず、端末はMacbookで行うという縛り** も試してみたいものでした。開発の第一弾が終了し、AppStoreにもリリースされましたので、ここで今までのところをまとめてみたいと思います。

## Qolkの話

まずは、Qolkの説明を簡単にしたいと思います。

### 特徴

- スワイプでの記事送り。
- 充実したプロフィール表示。
- 記事のストック、ユーザー・タグのフォロー。
- 画像を多く利用した楽しい閲覧体験。
- 様々な切り口からの検索対応。

![iOS Simulator Screen Shot 2015.09.27 15.05.22.png](https://qiita-image-store.s3.amazonaws.com/0/24041/b7a34549-2d70-2fb9-c4d5-78e273995f2e.png "iOS Simulator Screen Shot 2015.09.27 15.05.22.png")

記事の一覧画面です。画像のある記事は一覧に画像を出すようにしています。

![iOS Simulator Screen Shot 2015.09.27 15.03.11.png](https://qiita-image-store.s3.amazonaws.com/0/24041/4f70f1b6-4f12-313a-be98-88f32c695405.png "iOS Simulator Screen Shot 2015.09.27 15.03.11.png")

記事の画面です。スワイプでページめくりができます。

![iOS Simulator Screen Shot 2015.09.27 15.02.41.png](https://qiita-image-store.s3.amazonaws.com/0/24041/284cf253-477d-86bb-c308-55f6569ca714.png "iOS Simulator Screen Shot 2015.09.27 15.02.41.png")

タグのページです。タグ一覧の表示とフォローができます。

![iOS Simulator Screen Shot 2015.09.27 15.02.46.png](https://qiita-image-store.s3.amazonaws.com/0/24041/1741c5ee-c102-5746-5c45-4a2bb6ef960a.png "iOS Simulator Screen Shot 2015.09.27 15.02.46.png")

プロフィールのページです。ユーザーの投稿やストックした記事、フォローしているタグを見ることができます。ユーザーのフォローもここからすることができます。

こんな感じです。普通のアプリです。作りもAppleが想定している挙動の中で自然にしようと思っているので強引に作り込んでいるところはないと思います。

### 今後のこと

直近では下記のことに取り組みたいと思っています。Swift2.0に早く対応したい。

- パフォーマンスの改善
- 明らかなバグの改善
- コメント表示・追加
- 自分の記事の編集
- 検索・マイフィードの強化
- Swift2.0対応

## 開発の話

冒頭で述べた通り、開発時には下記の2点の縛りを設けてみました。さらに、新しく登場したライブラリなども使っています。その辺りのことを書いていきたいと思います。

- Cocoapodsを一切使わない（基本、Carthageで行う）
- 新しいMacbookでの開発

### Cocoapodsを一切使わない開発について

[Carthage](https://github.com/Carthage/Carthage)でやりました。fabricのマニュアルインストールがうまくいかなかったり、Google Analyticsの導入が面倒だったり、Carthageに対応していないライブラリがいくつもあったり、Carthage対応しているもののビルドできないものがあったりと、いくつも挫折のタイミングがありましたが、のり切りました。とりあえず初回リリース時点ではCocoapodsを使っていません。

Carthageのみの開発について是か非かと言われると迷いますが、個人開発など時間的に余裕があればありなんじゃないかなと思います。利点はCocoapodsのビルド時間がかからないのと、気持ち的にすっきりすることです。

振り返ってみると、約26のオープンソースライブラリを利用していました（ほとんど使っていないのもあり整理が必要）。そのうち、下記のものについては特別な対応が必要でした。

- [DateTools](https://github.com/MatthewYork/DateTools): Carthage対応されていなかったので、プルリクを送って対応してもらった。　-> 11/15時点で対応済み
- [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON): 当初、Carthage対応されていず、プルリクがあるもののマージされていなかったので、フォークしてCarthage対応しているリポジトリを利用した。　-> 11/15時点で対応済み
- [Async](https://github.com/duemunk/Async/releases): 自分でフォークしてCarthage対応した。　-> 11/15時点で対応済み
- [FlatUIColors](https://github.com/brynbellomy/FlatUIColors): Carthage対応されていなかったので、プルリクを送って対応してもらった。　-> 11/15時点で対応済み
- [NVActivityIndicatorView](https://github.com/ninjaprox/NVActivityIndicatorView): Carthage対応されていなかったので、フォークして利用した。プルリクを送っているが現時点で未対応。 -> 11/15時点で対応済み
- [TagListView](https://github.com/xhacker/TagListView): Carthage対応されていなかったので、プルリクを送って対応してもらった。　-> 11/15時点で対応済み
- [KINWebBrowser](https://github.com/dfmuir/KINWebBrowser): 依存している[ARChromeActivity](https://github.com/alextrob/ARChromeActivity)と[TUSafariActivity](https://github.com/davbeck/TUSafariActivity)ともにCarthage未対応だったので、フォークしてCarthage対応した。ブラウザは自作すればよかった汗。　-> 11/15時点で未対応
- [GoogleAnalytics](https://developers.google.com/analytics/devguides/collection/ios/v3/sdk-download?hl=ja): マニュアルインストール
- [fabric](https://get.fabric.io/): 初回リリースでの導入を諦めた

書き出してみるとわかるのですが、対応する必要があったのはそこまで有名ではないライブラリが大半です。規模も小さかったりするので、だいたい一つ30分くらいでCarthage対応したり、ついでにプルリクを送ることができました。

Carthageのみで開発したことによりプロジェクトを綺麗な状態のまま保つことができました。Cocoapodsのビルド時間がかからないので、毎回のビルドがスムーズになりました。

デメリットとしては、Macbookでの `carthage update` がものすごい遅いということでした。

### Macbookでの開発について

```bash
$ cloc QiitaApp
     109 text files.
     107 unique files.
      32 files ignored.

http://cloc.sourceforge.net v 1.64  T=0.48 s (159.0 files/s, 18110.3 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Swift                           59            996            472           5544
CSS                              1            103              5            395
C/C++ Header                    11            173            620            292
JSON                             5              0              0            159
Javascript                       1              1              2             10
-------------------------------------------------------------------------------
SUM:                            77           1273           1099           6400
-------------------------------------------------------------------------------
```

だいたい6400行くらいだったんですね。このくらいの規模でMacbookで開発する際に不便に感じたことはほぼなかったと言っても良いと思います。仕事ではMacbook proを使っていますが、特に遜色のない感じでした。ちなみに、利用しているMacbookはこんな感じです。アップグレードしています。

![スクリーンショット 2015-09-28 00.17.23.png](https://qiita-image-store.s3.amazonaws.com/0/24041/80f834b1-3249-a995-08a7-140ccf00fd17.png "スクリーンショット 2015-09-28 00.17.23.png")

ただ、ひとつ難点は `carthage update` がものすごい遅いというくらいでした（上記の構成で10分くらいかかることも...）。ちょっとした合間にすぐに作業に取りかかれるMacbookは優秀でした！

### 利用したライブラリについて

主なSwiftのライブラリとその周辺事情を書いてみます。

今回はMVVMを勉強しながら作っています。つなぎ目は **[SwiftBond](https://github.com/SwiftBond/Bond)** を使いました。通信部分は **[Alamofire](https://github.com/Alamofire/Alamofire)** を用いて行い、返ってきた値を **[SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON)** にラップするという普通の構成です。RouterなどもほぼAlamofireのREADMEにある通りに作りました。通信の結果はPageResponse, ErrorResponseというstructに必要な情報をまとめたうえで、 **[BrightFutures](https://github.com/Thomvis/BrightFutures)** を用いてプロミスで受け取れるようにしました。

AlamofireManagerなるものを作って、Alamofireの共通の通信処理をまとめてログなどを仕込みました。QiitaAppManagerなるものがAPI毎のメソッドを持っていて、必要があれば受け取った値に処理を加えたりDBへの保存を差し込みました。

AutoLayoutはMasonryのSwift版である **[SnapKit](https://github.com/SnapKit)** を使いました。DBは **[Realm](https://github.com/realm/realm-cocoa)** を使いました。今までSDWebImageで行っていたところの処理は **[Kingfisher](https://github.com/onevcat/Kingfisher)** を使いました。今回はそこまで深い処理は書いていないのですが、読み込みやキャンセルなどの基本的な部分は同じように使えたのでよかったです。キーチェーン周りは、 **[KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess)** を利用しました。

リソース管理にR.swiftを使いたいと思っていたんだけど、Swift2.0に移行した時の影響が大きいかもと思って我慢しています。

主なところでいうとこんな感じで、そこまでたくさん試したわけじゃなかったみたいです。個人的にはAlamofire+SwiftyJSON+BrightFuturesのあたりが綺麗に連携できたなという感じです。

## 最後に

夏にアプリをリリースしたいと思いつき、8月の中旬頃から風邪や家族の用事などでとりかかれない場合を除き、土日はずっとこれの開発に当てていました。シルバーウィークに一気に見た目を整えて申請という流れです。

久しぶりにアプリを作ってみてやっぱり一つ作り上げるのは大変だと思ったと同時にとても楽しい経験でした。ゆっくり綺麗に作りたいと思いつつも後半急いでバグを組み込んでしまったのでそこは、後ほど整理したいと思っています。全体的にシンプルに作っているので、改修とかそこまで手間がかからないはず！

よろしければダウンロードしていただいてフィードバックなどいただけるとありがたいです。

- [Qolk - AppStore](https://itunes.apple.com/jp/app/qolk-for-qiita-cozy-qiita/id1042929986?l=ja&ls=1&mt=8)

## 追記（リジェクトとモチベーション）

ここまでは9月28日、最初の申請の日に書きました。その後、いろいろあってリリースが今日になりました（10/21）。

### 1回目のリジェクト

くらいました。リジェクトです。[14.3項](https://developer.apple.com/app-store/review/guidelines/#personal-attacks)に該当したといってバイナリリジェクトされました。14.3項はよくある方かなと思うのですが、簡単に言うと「不適切なコンテンツからユーザーを守るべき」というものです。

- [App Store Review Guidelines - Apple Developer](https://developer.apple.com/app-store/review/guidelines/#personal-attacks)

Appleからは利用規約に同意させるべき、不適切なコンテンツやユーザーをブロックできるようにすべき、報告できるようにすべき、運営側は削除することができるべきなどなどいくつもの要求がありました。ただ、今回はQiitaのクライアントなので自分でコンテンツを管理できるわけではありません。いろいろ考えたのですが、できるだけのことはした上で、Qiitaの管理がしっかりしていることなどをAppleに伝え、再度申請しました。（このタイミングで急いで修正したため、バグを埋め込んでしまいました Ah...）

これに関してはクリアできないケースも考えました。せっかく作ったアプリがリリースされない可能性があるということで、かなりモチベーションが下がりました。

[良いウェブサービスを支える「利用規約」の作り方](http://www.amazon.co.jp/%E8%89%AF%E3%81%84%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E3%80%8C%E5%88%A9%E7%94%A8%E8%A6%8F%E7%B4%84%E3%80%8D%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E9%9B%A8%E5%AE%AE%E7%BE%8E%E5%AD%A3-ebook/dp/B00K2RFJK2/)を読んだりしました。良い本でした。

### 2回目のリジェクト

名前がよくないということでリジェクトされました。Qiitaを連想させるから、`for Qiita`などに変えてくれというものです。これは予想していたのですが、すでにストアに並んでいるアプリもアプリ名にQiitaが入っているものがあるのでなんとかなるかなと思っていたのですがダメでした。

もともとは **Qiitaholic** という名前で気に入っていたのですが、ここで何人かの人に相談させていただいた結果、目の前のヒントと直感と語感で **Qolk** としました。

### リジェクトを超えて

リジェクトされて再審査という時間はかなりモチベーションが下がりました。特に、1回目のリジェクトは超えられないかもという思いもあり、別のアプリを作ろうかななどと考えたりしていました。開発は中断していました。

ただ、今回はなんとか超えることができたので、また、ちょっとずつ良くしていきたいと思っています。

## Qolk

明らかなバグがあったりパフォーマンスが悪かったりと、まだ完全体ではないですが、幾つかの問題は修正して次のバージョンも申請中です。ぜひ、今後ともよろしくお願いいたします。

- [Qolk - AppStore](https://itunes.apple.com/jp/app/qolk-for-qiita-cozy-qiita/id1042929986?l=ja&ls=1&mt=8)

## 参考

- [Qiita](http://qiita.com/)
- [Qiita API v2ドキュメント - Qiita:Developer](https://qiita.com/api/v2/docs)

## 更新

11/15時点で上記Carthage未対応のライブラリはKinWebBrowserを除きすべてCarthage対応になっていました〜。