UITableViewの要素を非同期に設定する

このページと、iPhoneDeveloperCenterのLazyTableImagesというサンプルを参考に実装。
ほとんどLazyTableImagesを真似たものだけど、必要な部分だけ取り出してGithubにおいた。
AsyncTableViewSample
ざっくりとした方針は、

  • cellForRowAtIndexPathの中で、
    • キャッシュヒットしたらそれを表示
    • なければ、デフォルト画像を表示、
      • この時、テーブルが動いてなければ、画像ロードを投げておく(非同期)
  • テーブルの動きが止まったら,
    • 今見えているセルの画像ロードを投げておく(非同期)
  • 画像ロードのレスポンスが届いたら、
    • 該当テーブルセルに画像を表示
    • キャッシュに画像を入れておく


なぜ「テーブルが動いていないとき」にこだわるかというと、

  • UITableViewは、表示に困らない最低限のセルしか作らない。
  • テーブルを動かし、非表示になったセルオブジェクトはキューに入れられる。
  • キューに入れられたオブジェクトは、表示領域用に再利用、使い回しされる。

から。
セルは中古品を使いまわされます。
cellForRowAtIndexPathの中でcellの設定をしないと、前の持ち主のデータがそのまま表示されちゃったりする。


また、非同期で画像取得をしないと、処理がブロックされてしまい動きがガクガクになる。
最初、cellForRowAtIndexPathの中で毎回webにアクセスしていたら、ガックンガックンだった。