Swiftの勉強をするために、Swiftでアプリを一から作ってみた話

この記事は[Swift Advent Calendar](http://qiita.com/advent-calendar/2014/swift) 12月23日の記事です。
アドベントカレンダーは後半ほどネタが出尽くすので不利ですね。
自分はこの2ヶ月半ほどプライベートの時間を使ってSwiftで新しくアプリを作っていたので、それについて考えていたこと、感じたことをつらつらと書き下してみたいと思います。

[2014/12/28 追記]
今朝、アプリがリリースされました！！
[Rebuilt](https://itunes.apple.com/jp/app/rebuilt/id951037452?mt=8)

# きっかけ
2014/6/3にWWDCでSwiftが発表され非常に気になっていました。
しかし、当時の自分は業務でアプリ開発から離れており、他に優先順位の高い事柄があったので積極的に勉強することを避けていました。
Xcodeベータは安定していない、Swiftの仕様もコロコロ変わる中、学習効率を重視するのであれば安定版がリリースされてから勉強したほうが良いとも思いました。
新しい技術が出てくるタイミングはチャンスなので、第一人者のポジションを取ってやるぜ！という気概がある人は、最初のアナウンスからリアルタイムで追いかけ続け、フォーラムやコミュニティで存在感を出していくと良いと思います。

9月になりバージョン1.0やiOS8が正式リリースされ、自分の中でSwiftの勉強をする機運が高まりました。
過去の経験から、ある程度しっかり身につけるためには一からアプリを開発してリリースまでしてみるのが近道であると感じていたので、10月から新しいアプリの開発を開始しました。

# 作ったアプリ
ポッドキャスト[Rebuild](http://rebuild.fm/)の"非公式"クライアントアプリ「Rebuilt」を作りました。

実は2014/12/23の時点で申請は通っておらず、 Waiting for review 8日目。
現在 [iTunes Connectのholiday shutdown](https://developer.apple.com/news/?id=12082104a) なので、リジェクトされなければぎりぎり年内リリースできるかも、といったスケジュール感です。
本当はこの記事に間に合わせたかったのですが、残念です。
業務で年末に申請するときは気をつけましょう。

![AppIcon76x76@2x.png](https://qiita-image-store.s3.amazonaws.com/0/8748/0bd1f4a5-b05e-b4e9-a6d0-2eeb3643a54a.png)

![iOS Simulator Screen Shot 2014.12.13 22.03.56.png](https://qiita-image-store.s3.amazonaws.com/0/8748/b9588e91-06f7-afc4-4f96-46b190721d51.png)

Rebuildは毎回楽しみに聞いているのですが、iPhone標準のポッドキャストアプリはいまいち使い勝手が良くなかったのと、Android版を[@rejasupotaro](https://twitter.com/rejasupotaro)氏が作っていてなかなか良かったので、iPhone版も欲しいと思っていました。
標準ポッドキャストアプリと比較して、

- 新しいエピソードが配信されるとプッシュ通知される。
- Show notes をアプリの中で一覧表示できてWebビューで閲覧することができる。
- After show のエピソードにはタイトルにアイコンが付く。

といった機能がついています。

# 開発環境
アプリの開発環境は、

- Xcode6.1.1
- Swift
- Autolayout
- iOS8
- パッケージ管理にcocoapods
- コマンドラインビルドに[shenzhen](https://github.com/nomad/shenzhen)
- リポジトリはGithubのプライベートリポジトリ
- 開発メンバーとのコミュニケーションはslack
- アプリ配布は[DeployGate](https://deploygate.com/)
- 画像素材のやりとりはDropbox
- プッシュ通知と新着チェックのためのバックグラウンドジョブは[Parse.com](https://parse.com/)
- アクセス解析はGoogle Analytics

を使いました。


ライブラリは、

- 通信は[AFNetworking](https://github.com/AFNetworking/AFNetworking)
- プッシュ通知は[Parse.com](https://parse.com/)
- RSSパーサーに[MWFeedParser](https://github.com/mwaterfall/MWFeedParser)
- HTMLパーサーに[HTMLReader](https://github.com/nolanw/HTMLReader)
- 画像取得とキャッシュに[SDWebImage](https://github.com/rs/SDWebImage)

を使いました。


Rebuildにはエピソード毎に[Show notes](http://rebuild.fm/72/)と呼ばれるリンク集があり、アプリの中ではShow notes一覧に画像を付けてリスト表示しています。
![iOS Simulator Screen Shot 2014.12.13 22.04.21.png](https://qiita-image-store.s3.amazonaws.com/0/8748/c21c4a0e-48e9-cc98-59b3-d9c70fbed2ff.png)
この画像は、[140noteさんのOGP（Open Graph Protocol）データ取得API](http://140note.hitonobetsu.com/apipage/ogp)を利用して取得しています。
ただ、OGPで画像を設定していないページも割りと多かったので、取得できなかった場合は[HeartRailsさんの HeartRails Capture](http://capture.heartrails.com/help/use_api) を使用して、Webページのキャプチャを取得しています。
（ありがとうございます。）

# 開発の流れ
開発は、平日の昼休みと夜を使って進めました。

自分はデザイン周りが苦手なのと、一人だと何かと心が折れがちになるので、途中途中で仲間を増やしていきました。
また、最初から機能を詰め込みすぎず、適当なところで開発スコープを切ってリリースすることを意識しました。
以下がその流れです。

1. 一人で開発を始める。
1. 会社のデザイナーの人とお昼ごはんを食べている時に、作っているアプリを見せる。食いついてきたら巻き込む。
1. ある程度動くようになってきたら、SNSで身近な人に向けてベータテスター募集をしてみる。
1. 開発に興味がありそうな人がいたら、Githubプライベートリポジトリに招待する。 pull request 大歓迎。
1. 適当なところでリリースする。

実際、開発の初期から会社のデザイナーの人に参加してもらうことができ、自分がデザインする何倍も良い仕上がりになりました。
開発に関しても、興味を持ってくれたエンジニア仲間が意見をくれたりpull requestをくれたりしました。
仲間ができ、開発を通じてコミュニケーションするのはとても楽しいものです。

最初から[DeployGate](https://deploygate.com/)を使っておくと、迅速に巻き込むことができるので便利です。

# とにかくSwiftで開発してみる

やっとSwiftの話です。
Objective-Cはある程度経験があったので、事前にSwiftの勉強はせず開発しながら学ぶスタンスで臨みました。
Swiftなんてチョロい、すぐに慣れるだろうと思っていたら全然全くそんなことありませんでした。

### Optional型
とにかくこれが最初で最大のハマりどころでした。
挙動に疑問が浮かんだら、Playgroundを使ってひたすら動かしながら慣れていきました。

### クロージャと循環参照
Swiftになったからといってすべて自動になるわけでもなく、気をつけなければいけないのは相変わらずでした。
その上で、Objective-C の時のように「weakポインタに突っ込んでからblockの中で使う」というやり方ではなく、クロージャの先頭でキャプチャリストとして対象オブジェクトを指定する形になりました。
この辺りに関しては、実はまだしっくりきていない。

### getter/setter
Objective-Cでは、プロパティのアクセサメソッドを使い、値をセットするタイミングで色々と処理を走らせることをやっていたのですが、同じことをしようとした時にSwiftのget/setは様子が違い戸惑いました。
どうやらSwiftのget/setは、セットしたプロパティの値を使って他のプロパティの値を計算して変更する、ゲットしたいプロパティの値を他のプロパティの値を使って計算し取得する、という使い方が正しいみたいです。
自分が以前やっていたような値を設定するときに他の処理を走らせる場合は、didSetやwillSetを使うべきです。
これはKVO（キー値監視）で、Objective-Cの時よりも簡単に記述することができます。

### #pragma mark
Objective-Cでは、メソッドのまとまりを#pragma markで区切ることでXcodeのFunction Menuに表示させることが出来ました。
コメントの代わりにもなり、ソースコードの見通しもよくなります。
しかしSwiftでこれを書いたらXcodeは認識をしてくれませんでした。
実は構文が変わっていて、

```objc
#pragma mark - hoge
```

が

```swift
// MARK: - hoge
```

になりました。

# Swiftを学ぶ
他にも色々な場面でハマりながらも、なんとかある程度形になってきました。
ある程度動くようになると、果たしてこの書き方は正しいのだろうか、もっと良い書き方はないのだろうか、という気持ちが出てきます。
そういうタイミングで、自分は以下の二冊の本を読みました。

<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798042196/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/51fvzOOl--L._SL160_.jpg" alt="Swiftスタートアップガイド" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798042196/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank">Swiftスタートアップガイド</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 14.12.23</div></div><div class="amazlet-detail">掌田 津耶乃 <br />秀和システム <br />売り上げランキング: 29,344<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798042196/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jpで詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>

<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4797380497/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/41-FrdK0A2L._SL160_.jpg" alt="詳解 Swift" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4797380497/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank">詳解 Swift</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 14.12.23</div></div><div class="amazlet-detail">荻原 剛志 <br />SBクリエイティブ <br />売り上げランキング: 2,259<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4797380497/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jpで詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>

一度自分の頭で悩んだあとに書籍で体系的に学ぶことで、ストンと頭に入ってきます。


# おわりに
アプリを申請するのは丸々一年ぶりくらいになるのですが、Swift以外にも変わっている所が数多くあって「へー」とか「えー」とかブツブツ言いながら開発をしていました。
特にiTunes Connectの変わりっぷりにはかなり戸惑いました。
こまめにキャッチアップしないと置いてかれてしまいますね。

自分の場合、Objective-Cを初めてさわったときも、Objective-Cを勉強するのではなく「とにかくStoreでアプリを売ってみる」というのを目標にアプリ開発を始めました。
Objective-CでもSwiftでも、大半の人はアプリ開発のために勉強するのだと思います。
もしこれから勉強をしたいという人は、言語の勉強をしてからアプリを作るのではなく、アプリを作りながら言語の勉強をすることをおすすめします。
どんなアプリでも良いので、ゼロから作ってリリースまでやってみることで、書籍やPlaygroundだけでは出てこない実践的な経験値を得ることができます。
何より、開発の過程で仲間ができたり、悩みながら試行錯誤したり、実際に使ってもらったりするのはとても楽しいことです。

アプリが無事リリースできたら、ここに追記したりSNSでアナウンスしようと思います。
もしよろしければ使ってみてください。

[2014/12/28 追記]
今朝、アプリがリリースされました！！
[Rebuilt](https://itunes.apple.com/jp/app/rebuilt/id951037452?mt=8)