LoginSignup
261
268

More than 5 years have passed since last update.

URLから画像を非同期に読み込む3種類の実装

Posted at

URLから画像を生成するときは、普通に実装すると以下のようになります。

ViewController.m
NSURL *url = [NSURL URLWithString:@"画像のURL"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];

しかし、この実装だとシングルスレッドで読み込むので、その間他の処理が止まり固まったように見えてしまいます。
なので、画像は非同期に読み込むことが必要になります。今回は非同期での画像読み込みの実装を3種類してみました。
3つの実装をまとめたソースコードは、こちらからダウンロードしてください。

  1. 一度読み込んだ画像をキャッシュしない。(UITableViewCellの画像)
  2. 一度読み込んだ画像をキャッシュして、再び読み込まない。(UITableViewCellの画像)
  3. UIImageViewのインスタンスに読み込み処理を任せて、それぞれで読み込む。(UIImageView)

1. 一度読み込んだ画像をキャッシュしない。

参考URL: ネット上の画像を表示させた UITableView をぬるぬる動作させる方法

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

    // この部分が重要
    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://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Apple_Computer_Logo_rainbow.svg/150px-Apple_Computer_Logo_rainbow.svg.png";
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL: [NSURL URLWithString: imageURL]]];

        dispatch_async(q_main, ^{
            cell.imageView.image = image;
            [cell layoutSubviews];
        });
    });

    return cell;
}

2. 一度読み込んだ画像をキャッシュして、再び読み込まない。

参考URL: UITableViewの要素を非同期に設定する

以下のクラスを組み込んで下さい。

  • Downloader.h (非ARC)
  • Downloader.m (非ARC)
CacheAsyncTableController.h
#import "Downloader.h"

@interface CacheAsyncTableController : UITableViewController

@property (nonatomic, strong) NSMutableDictionary *imageCache;
@property (nonatomic, strong) NSMutableDictionary *downloaderManager;

@end
CacheAsyncTableController.m
- (void)viewDidLoad
{
    [super viewDidLoad];

    // 非同期表示・キャッシュ用の配列の初期化
    self.imageCache = [NSMutableDictionary dictionary];
    self.downloaderManager = [NSMutableDictionary dictionary];
}

***(略)***

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

    if ([_imageCache objectForKey:indexPath]) {
        // すでにキャッシュしてある場合
        cell.imageView.image = [_imageCache objectForKey:indexPath];
    } else {
        if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
        {
            // キャッシュがない場合、読み込む
            [self startIconDownload:indexPath];
        }
    }

    return cell;
}


***(略)***

// 以下のメソッドを実装する(ソースコード参照)
- (void)startIconDownload:(NSIndexPath *)indexPath;
- (void)loadImagesForOnscreenRows;
- (void)downloader:(NSURLConnection *)conn didLoad:(NSMutableData *)data identifier:(id)identifier;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

3. UIImageViewのインスタンスに読み込み処理を任せて、それぞれで読み込む。

参考URL: 非同期通信で画像をロードする方法について

以下のクラスを組み込んで下さい。

  • AsyncImageView.h
  • AsyncImageView.m

UIImageViewを生成するところで、以下のように書きます。

AsyncImageViewController.m
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
NSString *imageURL = @"http://upload.wikimedia.org/wikipedia/commons/a/a5/Apple_gray_logo.png";
[imageView loadImage:imageURL]; // 画像を非同期で読み込む
261
268
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
261
268