Асинхронная загрузка картинок в iPhone

Наверное на эту тему есть достаточно материалов, в том числе и у Apple, но я опишу свой опыт и приведу свой код.
Задача следующая: для некоторого View, имеющего определенное количество subview в которые можно грузить изображения (UIImageView к примеру), нужно асинхронно загрузить некоторое количество изображений без блокировки основного UI.
Наш класс будет называться ImageLoader и будет иметь протокол ImageLoaderDelegate, что бы иметь возможность сообщить делегату, когда картинка уже «приехала»

ImageLoader.h

#import <Foundation/Foundation.h>
 
@protocol ImageLoaderDelegate; // Предварительное объявление протокола, что бы не иметь проблем
                                                     // с объявлением свойства delegate
 
@interface ImageLoader : NSObject {
    id <ImageLoaderDelegate> delegate; // Свойство для задания делегата
    int index; // Свойство для упрощения обработки полученной картинки в делегате
    NSMutableData *activeDownloadData; // Буфер для данных
}
 
@property (nonatomic, assign) id <ImageLoaderDelegate> 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]; // Вызываем метод делегата
    }
    [activeDownloadData release];
    [connection release];
}
 
- (void)dealloc {
    [super dealloc];
}
 
@end

Остается только вставить изображение в нужный view.

Один из вариантов я привожу ниже. Он использует свойство лоадера index что бы добраться до нужного view у которого свойство tag имеет такой же индекс.

...
- (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] initWithImage:[UIImage imageNamed:@"images.jpeg"]];
        [imgView setFrame:CGRectMake(10+(100*viewIndex), 50, 100, 100)];
        //    [imgView setBackgroundColor:[UIColor redColor]];
        [imgView setTag:viewIndex];
        [[self view] addSubview:imgView];
        [loader setIndex:viewIndex];
        [loader setDelegate:self];
        [loader loadImage:imgURL];
        [loader release];
        viewIndex++;
    }
}
 
- (void)appImageDidLoad:(UIImage* )image index:(int)index {
    NSLog(@"Image on main thread: %fx%f for view %d", image.size.width, image.size.height, index);
    for (UIView *tmp in [self view].subviews) {
        if ([tmp isKindOfClass:[UIImageView class]]) {
            if (tmp.tag == index) {
                [(UIImageView *)tmp setImage:image];
            }
        }
    }
}
...

Надеюсь материал кому-то будет полезен.