Наверное на эту тему есть достаточно материалов, в том числе и у Apple, но я опишу свой опыт и приведу свой код.
Задача следующая: для некоторого View, имеющего определенное количество subview в которые можно грузить изображения (UIImageView к примеру), нужно асинхронно загрузить некоторое количество изображений без блокировки основного UI.
Наш класс будет называться ImageLoader и будет иметь протокол ImageLoaderDelegate, что бы иметь возможность сообщить делегату, когда картинка уже «приехала»
ImageLoader.h
ImageLoader.m
Остается только вставить изображение в нужный view.
Один из вариантов я привожу ниже. Он использует свойство лоадера index что бы добраться до нужного view у которого свойство tag имеет такой же индекс.
Само собой в заголовочном файле нужно сделать наш класс делегатом для ImageLoader добавив в строку interface
Надеюсь материал кому-то будет полезен.
Задача следующая: для некоторого View, имеющего определенное количество subview в которые можно грузить изображения (UIImageView к примеру), нужно асинхронно загрузить некоторое количество изображений без блокировки основного UI.
Наш класс будет называться ImageLoader и будет иметь протокол ImageLoaderDelegate, что бы иметь возможность сообщить делегату, когда картинка уже «приехала»
ImageLoader.h
#import
@protocol ImageLoaderDelegate; // Предварительное объявление протокола, что бы не иметь проблем
// с объявлением свойства delegate
@interface ImageLoader : NSObject {
id delegate; // Свойство для задания делегата
int index; // Свойство для упрощения обработки полученной картинки в делегате
NSMutableData *activeDownloadData; // Буфер для данных
}
@property (nonatomic, assign) id delegate;
@property (nonatomic) int index;
- (void)loadImage:(NSString *)imageURLString; // Метод, который грузит катринку.
// Принимает на вход URL на картинку
@end
@protocol ImageLoaderDelegate
- (void) appImageDidLoad:(UIImage *)image index:(int)index; // Метод делегата, вызываемый по получению файла
@end
ImageLoader.m
#import "ImageLoader.h"
@implementation ImageLoader
@synthesize delegate, index;
- (void)loadImage:(NSString *)imageURLString {
NSURL *imgURL = [NSURL URLWithString:imageURLString];
NSMutableURLRequest *request = [NSURLRequest requestWithURL:imgURL];
NSURLConnection *newConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (newConnection) {
activeDownloadData = [[NSMutableData data] retain]; // Важный момент - сделать retain
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[activeDownloadData setLength:0]; //Если есть отклик от сервера, ставим буфер в 0
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[activeDownloadData appendData:data]; // Собираем данные файла
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
[connection release];
[activeDownloadData release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
UIImage *image = [UIImage imageWithData:activeDownloadData]; // Создаем из данных каритнку
if (delegate != nil) {
[delegate appImageDidLoad:image index:index]; // Вызываем метод делегата
}
else {
activeDownloadData = nil;
NSLog(@"Can't find delegate for ImageLoader");
}
[activeDownloadData release];
[connection release];
}
- (void)dealloc {
[super dealloc];
}
@end
Остается только вставить изображение в нужный view.
Один из вариантов я привожу ниже. Он использует свойство лоадера index что бы добраться до нужного view у которого свойство tag имеет такой же индекс.
Само собой в заголовочном файле нужно сделать наш класс делегатом для ImageLoader добавив в строку interface
...
- (void)viewDidLoad {
[super viewDidLoad];
viewIndex = 0;
NSArray *imageUrls = [NSArray arrayWithObjects: // Массив ссылок к картинкам
@"http://cdn5.iconfinder.com/data/icons/toys/128/teddy_bear_toy_1.png",
@"http://cdn5.iconfinder.com/data/icons/toys/128/teddy_bear_toy_4.png",
@"http://cdn5.iconfinder.com/data/icons/toys/128/teddy_bear_toy_5.png", nil];
for (NSString *imgURL in imageUrls) {
ImageLoader *loader = [[ImageLoader alloc] init]; // Создаем экземпляр загрузчика
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10+(100*viewIndex), 50, 100, 100)];
[imgView setTag:viewIndex]; // Ставим таг у ImgView в соотвествие с индексом картинки
[[self view] addSubview:imgView];
[imgView release];
[loader setIndex:viewIndex]; // Задаем индекс для экземпляра загрузчика
[loader setDelegate:self]; // Задаем делегатом этот же класс
[loader loadImage:imgURL]; // Собственно грузим картинку
[loader release];
viewIndex++;
}
}
- (void)appImageDidLoad:(UIImage* )image index:(int)index { // Метод делегата ImageLoader
for (UIView *tmp in [self view].subviews) { // Для всех subview в текущем view ищем UIImageView c tag = index
if ([tmp isKindOfClass:[UIImageView class]] && tmp.tag == index) {
[(UIImageView *)tmp setImage:image]; // Задаем свойство изображения
}
}
}
...
Надеюсь материал кому-то будет полезен.