画像をURLから取得するとき、非同期で行うようにしたいとおもいます。
まず、専用のImageViewのサブクラスをつくります。
LoadingImageView.h
@interface LoadingImageView : UIImageView - (id)initWithFrame:(CGRect)frame withUrl:(NSURL *)url; // Start load the image of the specified url. // Doesn't load the image if an image has been already set. - (void)startLoadImage; // Reload load the image of the specified url. // Load the image even if a connection was already created. - (void)reloadImage; // Cancel loading if requesting. - (void)cancelLoading; // Set the url of the image to reqeust. @property (nonatomic, retain) NSURL *imageUrl; @end
LoadingImageView.m
#import "LoadingImageView.h"
typedef enum LazyImageViewTag_ {
LazyImageViewTagIndicatorView = 1,
} LazyImageViewTag;
@interface LoadingImageView ()
- (void)setLoadingImage;
- (void)setLoadErrorImage;
@property (nonatomic, retain) NSURLConnection *connection;
@property (nonatomic, retain) NSMutableData *imgData;
@end
@implementation LoadingImageView
- (id)initWithFrame:(CGRect)frame withUrl:(NSURL *)url
{
self = [super initWithFrame:frame];
if (self) {
[self setImageUrl:url];
}
return self;
}
- (void)startLoadImage
{
if (self.image) return;
if (self.connection)
{
[self.connection cancel];
}
[self setImgData:[NSMutableData data]];
NSURLRequest *req = [NSURLRequest requestWithURL:self.imageUrl];
NSURLConnection *con = [NSURLConnection connectionWithRequest:req delegate:self];
[self setConnection:con];
[self setLoadingImage];
}
- (void)reloadImage
{
[self setImage:nil];
[self startLoadImage];
}
- (void)cancelLoading {
[self.connection cancel];
[self setConnection:nil];
if (self.image == nil) {
[self setLoadErrorImage];
}
}
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.imgData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[self setLoadErrorImage];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIActivityIndicatorView *iv = (UIActivityIndicatorView *)
[self viewWithTag:LazyImageViewTagIndicatorView];
if (iv) [iv removeFromSuperview];
[self setImage:[UIImage imageWithData:self.imgData]];
}
#pragma mark -
- (void)setLoadingImage
{
UIActivityIndicatorView *iv = (UIActivityIndicatorView *)
[self viewWithTag:LazyImageViewTagIndicatorView];
if (iv == nil)
{
iv = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
// [iv setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];
[iv setTag:LazyImageViewTagIndicatorView];
[self addSubview:iv];
}
iv.frame = self.frame;
iv.center = self.center;
[iv startAnimating];
[iv setHidden:NO];
//[self setBackgroundColor:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.3]];
[self setBackgroundColor:[UIColor clearColor]];
}
- (void)setLoadErrorImage
{
UIActivityIndicatorView *iv = (UIActivityIndicatorView *)
[self viewWithTag:LazyImageViewTagIndicatorView];
[iv removeFromSuperview];
[self setImage:nil];
//[self setBackgroundColor:[UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.4]];
[self setBackgroundColor:[UIColor blackColor]];
}
#pragma mark -
- (void)dealloc
{
[self setImageUrl:nil];
[self.connection cancel];
[self setConnection:nil];
[self setImgData:nil];
}
@synthesize imageUrl;
@synthesize connection;
@synthesize imgData;
@end
今回はmmasashi にお世話になりました。
参考にしてください。
http://d.hatena.ne.jp/mmasashi/20110924/1316940621
続きは、【サンプルコードあり】URLから画像を非同期に取得する2です。
他クラスからLoadingImageViewを使う方法です。
