iOS4でGCDとBlocksを使ってUITableViewへの非同期画像読み込みを書いてみる。
http://cocoatouch.sblo.jp/article/26626578.html みたいなことをGCD+Blocksでやってみた記録。コメントは間違っているかもしれない。実際のコードの抜粋で、tableView:cellForRowAtIndexPath:内のコードである。itemSpecはNSDictionaryであり、Amazonから引っ張った商品データや画像URLが入っている。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // (中略。cellの準備や再利用コード) // 表示すべきデータの読み込み NSMutableDictionary *itemSpec = [search_results objectAtIndex:[indexPath row]]; // タイトルとASINを表示 cell.itemTitle.text = [itemSpec objectForKey:@"Title"]; cell.itemASIN.text = [itemSpec objectForKey:@"ASIN"]; // 画像の読み込み。ここからが本題。 UIImage *itemImage; // キャッシュが無ければURLから読み込み開始。 if (!(itemImage = [itemSpec objectForKey:@"scaledImage"])) { // グローバル(非同期)キューとメイン(同期)キューの準備 dispatch_queue_t q_global, q_main; q_global = dispatch_get_global_queue(0, 0); q_main = dispatch_get_main_queue(); // タスク内で使うオブジェクトをretain [cell retain]; [itemSpec retain]; // 時間のかかる画像読み込み処理を非同期キューに登録 dispatch_async(q_global, ^{ // アクティビティ・インジケータを準備 UIActivityIndicatorView *indicator; indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; indicator.frame = cell.itemImage.bounds; indicator.hidesWhenStopped = TRUE; indicator.contentMode = UIViewContentModeCenter; [indicator startAnimating]; // 表示に即座に反映させるために、インジケータの表示タスクはメインキューに登録 // メインキューはメインスレッドで処理される。 dispatch_async(q_main, ^{ cell.itemImage.image = nil; [itemSpec removeObjectForKey:@"scaledImage"]; [cell.itemImage addSubview:indicator]; }); // 画像の読み込みとキャッシュへの登録 NSString *smallImageURLString = [itemSpec objectForKey:@"SmallImageURL"]; NSURL *smallImageURL = [NSURL URLWithString:smallImageURLString]; NSData *smallImageData = [NSData dataWithContentsOfURL:smallImageURL]; UIImage *image = [UIImage imageWithData:smallImageData]; if (image) { [itemSpec setObject:image forKey:@"scaledImage"]; } // 画像の反映、インジケータの消去もメインキューで行なう。 dispatch_async(q_main, ^{ cell.itemImage.image = image; [indicator removeFromSuperview]; [indicator release]; }); // タスクが終わったのでrelease [cell release]; [itemSpec release]; }); } else { // キャッシュがあればそちらを表示 cell.itemImage.image = itemImage; } return cell; }
CocoaはiOS4の開発から入った新参者ですが、従来の非同期処理コードがGCDとBlocksの導入により格段に書きやすくなっているものと想像します。