Наверное на эту тему есть достаточно материалов, в том числе и у 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]; // Задаем свойство изображения } } } ...
Надеюсь материал кому-то будет полезен.
