iOS

[iOS SDK] ネット上の画像を表示させた UITableView をぬるぬる動作させる方法

UITableView の Cell に、ネットから取得した画像を表示したい場合(上図)、次のようなコードになると思います(ARC で書いています)。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = @"rakuishi07";

    NSString *imageURL = @"http://rakuishi.com/wp-content/themes/rakuishi/image/rakuishi.png";
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL: [NSURL URLWithString: imageURL]]];
    cell.imageView.image = image;
    
    return cell;
}

これで動くっちゃ動くのですが、テーブルビューを動かしている時に画像ロードが発生して、操作がカクついてしまうので、あまりよろしくないです(カクついている時、ビーチボールを連想します)。

こういう時は、GCD の非同期通信を使用して、Blocks との組み合わせ技を使うと、テーブルビューがぬるぬるになるようです。

慣れるために、簡単なコードを書いてみました。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = @"rakuishi07";

    dispatch_queue_t q_global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t q_main = dispatch_get_main_queue();

    cell.imageView.image = nil;
    
    dispatch_async(q_global, ^{
        NSString *imageURL = @"http://rakuishi.com/wp-content/themes/rakuishi/image/rakuishi.png";
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL: [NSURL URLWithString: imageURL]]];
        
        dispatch_async(q_main, ^{            
            cell.imageView.image = image;
            [cell layoutSubviews];
        });
    });
    
    return cell;
}

このコードで動作させると先程までかくかくしていたのが、ぬるぬるになります。

これを基本に、読み込みまでインジケータを表示させたり、画像キャッシュを利用する(今のままでは、スクロールするたびに新しく読み込んでしまう)ためにどうすればいいかこれから勉強していこうと思います。

参考