Заполнение NSImage данными из асинхронного NSURLConnection

Я наткнулся на пресловутую стену, пытаясь выяснить, как заполнить NSImage данными, возвращаемыми из асинхронного NSURLConnection в моем настольном приложении (НЕ приложение для iPhone !!).

Здесь ситуация.

У меня есть таблица, которая использует пользовательские ячейки. В каждой пользовательской ячейке есть NSImage, который извлекается из веб-сервера. Чтобы заполнить изображение, я могу легко выполнить синхронный запрос:

myThumbnail = [[NSImage alloc] initWithContentsOfFile:myFilePath];

Проблема в том, что таблица блокируется до заполнения изображений (очевидно, потому чтосинхронный запрос). На большом столе это делает прокрутку невыносимой, но даже простое заполнение изображений при первом запуске может быть утомительным, если они имеют какой-либо значительный размер.

Поэтому я создаю асинхронный класс запросов, который будет извлекать данные в своем собственном потоке в соответствии сЯблоко'документация с, Нет проблем там. Я вижу, как данные извлекаются и заполняются (через мои файлы журналов).

У меня проблема, когда у меня есть данные, мне нужен обратный вызов в мой вызывающий класс (пользовательское представление таблицы).

У меня сложилось впечатление, что я могу сделать что-то подобное, но это не такне работает, потому что (яя предполагаю, что мой вызывающий класс действительно нуждается в делегате:

NSImage * myIMage;
myImage = [myConnectionClass getMyImageMethod];

В моем делегате класса соединения я вижу, что я получаю данные, я просто нене вижу, как передать его обратно вызывающему классу. мойconnectionDidFinishLoading Метод прямо из документов Apple:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do something with the data
    // receivedData is declared as a method instance elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);

    // release the connection, and the data object
    [connection release];
    [receivedData release];
}

Я надеюсь, что это простая проблема, которую нужно решить, но боюсь, что я нахожусь на пределе своих знаний по этому вопросу, и, несмотря на некоторые серьезные поиски в Google и пробуя много разных рекомендуемых подходов, я изо всех сил пытаюсь найти решение.

В конце концов у меня будет сложный механизм кэширования для моего приложения, в котором табличное представление проверяет изображения на локальном компьютере, прежде чем отправлять их с сервера, и, возможно, будет иметь индикатор выполнения, пока изображения не будут получены. Прямо сейчас даже местное население изображения может быть вялым, если изображение 's достаточно большие, используя синхронный процесс.

Любая помощь будет очень цениться.

Обновление решения

В случае, если кому-то еще нужно подобное решение благодаря БенуВот помощь, которую я придумал (в общем, модифицированный для публикации, конечно). Имейте в виду, что я также реализовал пользовательское кэширование изображений и сделал свой класс загрузки изображений достаточно универсальным, чтобы его можно было использовать в разных местах моего приложения для вызова изображений.

В моем методе вызова, который в моем случае был пользовательской ячейкой в таблице ...

ImageLoaderClass * myLoader = [[[ImageLoaderClass alloc] init] autorelease];

    [myLoader fetchImageWithURL:@"/my/thumbnail/path/with/filename.png"
                     forMethod:@"myUniqueRef"
                        withId:1234
                   saveToCache:YES
                     cachePath:@"/path/to/my/custom/cache"];

Это создает экземпляр класса myLoader и передает ему 4 параметра. URL-адрес изображения, которое я хочу получить, уникальная ссылка, которую я использую, чтобы определить, какой класс выполнял вызов при настройке наблюдателей уведомлений, идентификатор изображения, хочу ли я сохранить изображение в кэш или нет, а также путь в кеш.

Мой ImageLoaderClass определяет метод, вызванный выше, где я устанавливаю то, что передается из вызывающей ячейки:

-(void)fetchImageWithURL:(NSString *)imageURL 
           forMethod:(NSString *)methodPassed 
              withId:(int)imageIdPassed 
         saveToCache:(BOOL)shouldISaveThis
           cachePath:(NSString *)cachePathToUse
{

    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:imageURL]
                                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                                      timeoutInterval:60.0];

    // Create the connection with the request and start loading the data

    NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) {

        // Create the NSMutableData that will hold
        // the received data 
        // receivedData is declared as a method instance elsewhere

        receivedData = [[NSMutableData data] retain];

        // Now set the variables from the calling class

        [self setCallingMethod:methodPassed];
        [self setImageId:imageIdPassed];
        [self setSaveImage:shouldISaveThis];
        [self setImageCachePath:cachePathToUse];

    } else {
        // Do something to tell the user the image could not be downloaded
    }
}

вconnectionDidFinishLoading Метод я сохранил файл в кеш, если это необходимо, и сделал вызов уведомления для любых слушающих наблюдателей:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);

    // Create an image representation to use if not saving to cache
    // And create a dictionary to send with the notification    

    NSImage * mImage = [[NSImage alloc ] initWithData:receivedData];
    NSMutableDictionary * mDict = [[NSMutableDictionary alloc] init];

    // Add the ID into the dictionary so we can reference it if needed

    [mDict setObject:[NSNumber numberWithInteger:imageId] forKey:@"imageId"];

    if (saveImage)
    {
        // We just need to add the image to the dictionary and return it
        // because we aren't saving it to the custom cache

        // Put the mutable data into NSData so we can write it out

        NSData * dataToSave = [[NSData alloc] initWithData:receivedData];

        if (![dataToSave writeToFile:imageCachePath atomically:NO])
    NSLog(@"An error occured writing out the file");
    }
    else
    {
        // Save the image to the custom cache

        [mDict setObject:mImage forKey:@"image"];
    }

    // Now send the notification with the dictionary

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

    [nc postNotificationName:callingMethod object:self userInfo:mDict];

    // And do some memory management cleanup

    [mImage release];
    [mDict release];
    [connection release];
    [receivedData release];
}

Наконец, в контроллере таблицы установите наблюдателя для прослушивания уведомления и отправки его методу для обработки повторного отображения пользовательской ячейки:

-(id)init
{
    [super init];

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

    [nc addObserver:self selector:@selector(updateCellData:) name:@"myUniqueRef" object:nil];

    return self;
}

Задача решена!

Ответы на вопрос(3)

Ваш ответ на вопрос