非同期通信で画像をロードする方法について
UITableViewなどのスクロール系のViewでサムネイル画像を出す場合、下記のような記述ではメインスレッドで画像がロードされるため、ユーザーのUI操作に影響が出てしまいます。
NSURL *url = [NSURL URLWithString:@"URL"]; NSData *data = [NSData dataWithContentsOfURL:url]; [instanceOfUIImageView setImage:[[UIImage alloc] initWithData:data]];
こういう場合は非同期通信を行うのが定石だと思いますが、参考になるサンプルがあまり無かったので試しに作ってみました。UIImageViewを継承したUIAsyncImageViewクラスです。
UIAsyncImageView.h
画像URLの指定と、通信中止用のメソッドのみ定義しています。
#import <Foundation/Foundation.h> @interface UIAsyncImageView : UIImageView { @private NSURLConnection *conn; NSMutableData *data; } -(void)loadImage:(NSString *)url; -(void)abort; @end
UIAsyncImageView.m
NSURLConnectionによる非同期通信で画像データを取得しています。
connectionXXX系のメソッドは上記クラスのデリゲートメソッドです。
#import "UIAsyncImageView.h" @implementation UIAsyncImageView -(void)loadImage:(NSString *)url{ [self abort]; self.backgroundColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.2]; data = [[NSMutableData alloc] initWithCapacity:0]; NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; conn = [[NSURLConnection alloc] initWithRequest:req delegate:self]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ [data setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)nsdata{ [data appendData:nsdata]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ [self abort]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection{ self.image = [UIImage imageWithData:data]; self.contentMode = UIViewContentModeScaleAspectFit; self.autoresizingMask = UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight; [self abort]; } -(void)abort{ if(conn != nil){ [conn cancel]; [conn release]; conn = nil; } if(data != nil){ [data release]; data = nil; } } - (void)dealloc { [conn cancel]; [conn release]; [data release]; [super dealloc]; } @end
利用方法
UIImageViewと同様です。
loadImageを呼び出すと通信が開始され、データ取得完了した段階で画面に表示されます。
UIAsyncImageView *ai = [[UIAsyncImageView alloc] initWithFrame:CGRectMake(0,0,50,50)]; [ai loadImage:@"URL"]; [self.view addSubview:ai];
Flickrサンプル
FlickrのAPIを使ってUIScrollViewに表示するサンプルです。UITableViewではないですが、実機でもスムーズに動作しています。角丸にするライブラリも発見したので入れてみました。
参考
その他
UITableViewへ画像を表示する場合は、少し工夫がいるのでこれだけでは上手くいきません。iOS Dev Centerにある、LazyTableImagesというサンプルが参考になります。