UITableViewの要素を非同期に設定する
このページと、iPhoneDeveloperCenterのLazyTableImagesというサンプルを参考に実装。
ほとんどLazyTableImagesを真似たものだけど、必要な部分だけ取り出してGithubにおいた。
AsyncTableViewSample
ざっくりとした方針は、
- cellForRowAtIndexPathの中で、
- キャッシュヒットしたらそれを表示
- なければ、デフォルト画像を表示、
- この時、テーブルが動いてなければ、画像ロードを投げておく(非同期)
- テーブルの動きが止まったら,
- 今見えているセルの画像ロードを投げておく(非同期)
- 画像ロードのレスポンスが届いたら、
- 該当テーブルセルに画像を表示
- キャッシュに画像を入れておく
なぜ「テーブルが動いていないとき」にこだわるかというと、
- UITableViewは、表示に困らない最低限のセルしか作らない。
- テーブルを動かし、非表示になったセルオブジェクトはキューに入れられる。
- キューに入れられたオブジェクトは、表示領域用に再利用、使い回しされる。
から。
セルは中古品を使いまわされます。
cellForRowAtIndexPathの中でcellの設定をしないと、前の持ち主のデータがそのまま表示されちゃったりする。
また、非同期で画像取得をしないと、処理がブロックされてしまい動きがガクガクになる。
最初、cellForRowAtIndexPathの中で毎回webにアクセスしていたら、ガックンガックンだった。