はてなインターンのサンプルコードを読んでの感想

はてなさんが

はてなインターンで利用したiOSアプリ等のサンプルコードを公開しました - Hatena Developer Blog

という素敵なサンプルコードを公開してくれたので、好き勝手に感想を書いてみたいと思う。本来は Web アプリ側も動かしたかったんだけど、ウマく環境が作れなかったのでアプリはコードを読んだだけで動かしてはないです。あと、細かい検証とかしてないので勘違いとかしていると思うので指摘してください。

参考になった真似したい

NSError と UIAlertView の使い方

NSError の内容ベースでエラーアラートを出すのは理にかなっていると思った。OS 側が返す NSError は期待する値が入っていない不親切な場合があるので、オリジナルの NSError から一度適切な値を持った NSError を再生成して返すクラスを介したらいいのかもしれない。

すっきりした UIViewController

iOS アプリを作り慣れていない人は特に直接ネットワーク処理を書いてしまったりモデルの管理コードを書いてしまいがちで UIViewController の肥大化するのがありがちなパターンだと思う。しかし、このサンプルはネットワーク処理、モデル管理等を綺麗に分けているのは見習うべきだと思った。

通信とモデルの管理の関係

普段僕は Web API を叩くクラスとそれを元にモデル生成するのを同じクラスに書いていたけど、このコードのようにネットワークはシンプルに Web API を適切に触ることだけにし、パースやモデルの生成、管理はモデル管理クラスに分けた方が綺麗だし、のちのメンテナンス性や拡張性が確保されていいと勉強になった。

isEqual:hash をちゃんと実装

結構面倒で実装してないときがあるんだけど、モデルクラスがちゃんと isEqual と hash メソッドをオーバーライドしているのが素晴らしい。特に hash メソッドを実装するのを忘れていると NSSet に突っ込んだ時の振る舞いが期待通りにならずに軽くハマるので注意。

KVO をウマく使っている

KVO を使って ViewController がモデルを見ているあたりは Mac アプリ実装経験者っぽくてなんか素敵。NSErrorlocalizedFailureReason とか使っている点も同様。KVO を使って、TableView の更新をかけているのは凄く勉強になる。mutableArrayValueForKey: は知らなかった。勉強になった。

NSIndexSet の使い方

indexSet をうまく使っているのは素敵だと思った。 mattt が WWDC でも言っていたので使う機会があったら自分も使いたいと思ってる。

気になったところ

UIAlertView+NSError

self.message = [[NSArray arrayWithObjects:[error localizedFailureReason], [error localizedRecoverySuggestion], nil] componentsJoinedByString:@"\n"];

一瞬、[error localizedFailureReason]nil だったら落ちるんじゃないかと思ったけど、よく考えると arrayWithObjects:nil 終端として動作するので落ちない。[error localizedFailureReason][error localizedRecoverySuggestion]nil なら self.message はカラのままで済むのでスマート。ただ実際にあるかどうかはわからないが、逆にいうと [error localizedRecoverySuggestion] が入っていて[error localizedFailureReason]nil を返す場合には、先に渡されている nil の評価がされてしまって仮に値が入っていても [error localizedRecoverySuggestion]self.messagenil となる。この挙動を忘れているとある日ハマる。もっとマジメに実装するなら NSMutableArraynil チェックをしながら足していく感じになるのかもしれない。

NSDictionary に入れる値の nil チェック

IBKMInternBookmarkAPIClient が引数の nil チェックもせずに NSDictionary に突っ込んでいるのは落ちる可能性があるので危険。使う側が意識すれば落ちないだろうけど、渡されたデータの妥当性チェックはデータをもらう側に責任があると思うのでチェックした方がいいと思う。

addObserver:~ したら remove~ する

KVO の監視開始、NSNotificationCenter への登録をしても、それらの解除を書いていないのは良くない。

Be sure to invoke removeObserver: or removeObserver:name:object: before notificationObserver or any object specified in addObserver:selector:name:object: is deallocated.

NSNotificationCenteraddObserver:selector:name:object: にも書いてある。

NSNotificationCenter の remove は複数回読んでも害はないけど、KVO の remove は必ず add を一対でないと行けない(add していない状態で remove すると落ちる)のでライフサイクル的に一対になるようなところに入れるしないといけないので注意が必要。

24時間表示を Off でもちゃんと機能するように NSDateFormatter を使う

NSDateFormatter に locale を "en-US" でセットしていないけど、24時間表示を Off にしている端末でも期待する動作をするのか不安。timeZone を指定していると大丈夫なんだろうか?未検証。

まとめ

気になる点はあるけど、これだけ綺麗にまとまって、なおかつそれなりに実戦経験がある人でもやってなさそうだったり知らなそうなことをサラッと見せてくれているので、このコードで Objective-C / Cocoa を勉強するインターン生は幸せもんだなぁと思った。僕も来年インターンで入れないかな?