はてなさんが
はてなインターンで利用した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 アプリ実装経験者っぽくてなんか素敵。NSError
の localizedFailureReason
とか使っている点も同様。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.message
は nil
となる。この挙動を忘れているとある日ハマる。もっとマジメに実装するなら NSMutableArray
に nil
チェックをしながら足していく感じになるのかもしれない。
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.
と NSNotificationCenter
の addObserver:selector:name:object:
にも書いてある。
NSNotificationCenter
の remove は複数回読んでも害はないけど、KVO の remove は必ず add を一対でないと行けない(add していない状態で remove すると落ちる)のでライフサイクル的に一対になるようなところに入れるしないといけないので注意が必要。
24時間表示を Off でもちゃんと機能するように NSDateFormatter を使う
NSDateFormatter
に locale を "en-US" でセットしていないけど、24時間表示を Off にしている端末でも期待する動作をするのか不安。timeZone を指定していると大丈夫なんだろうか?未検証。
まとめ
気になる点はあるけど、これだけ綺麗にまとまって、なおかつそれなりに実戦経験がある人でもやってなさそうだったり知らなそうなことをサラッと見せてくれているので、このコードで Objective-C / Cocoa を勉強するインターン生は幸せもんだなぁと思った。僕も来年インターンで入れないかな?