Как асинхронно загружать много изображений и помещать их в imageView ячейки tableView - PullRequest
0 голосов
/ 31 января 2011

Я хотел бы знать, как я могу асинхронно загружать много изображений (ссылка анализируется через xml) и помещать их в ячейку tableView.Я попробовал учебник MarkJ, и он работал отлично, за исключением того факта, что я хочу, чтобы они отображались в imageView ячейки.Если бы вы могли сказать мне, как это сделать, это было бы здорово.

Ответы [ 2 ]

3 голосов
/ 01 февраля 2011

У меня похожий случай, но мой формат данных - JSON, а не xml.Загрузка и асинхронная часть должны быть очень похожи.Я решил попробовать это с блоками Objective-C и методом dispatch_async в GCD.Важные части моего кода приведены ниже, с некоторыми ненужными деталями.

У меня есть NSDictionary, который я использую для кэширования изображений, называемых изображениями.Первый шаг - проверить, есть ли у меня изображение для текущего NSIndexPath.Если так, я просто возвращаю это изображение.Если нет, я создаю изображение заполнителя, запускаю загрузку реального изображения и возвращаю заполнитель.

Часть «начать загрузку реального изображения» состоит из проверки, существует ли очередь, которую я хочу использовать, уже существует, и если она не создается.Затем я выполняю асинхронный вызов в фоновом потоке для удобного метода NSData dataWithContentsOfURL.Это блокирующий вызов, но он работает в фоновом режиме, поэтому пользовательский интерфейс остается отзывчивым.Когда вызов возвращается, я создаю UIImage из данных, кэширую изображение и извлекаю ячейку для indexPath.Затем я делаю еще один вызов dispatch_async, который просто устанавливает свойство imageView.image для ячейки.Ключевым моментом здесь является использование dispatch_get_main_queue () для получения ссылки на очередь, которая управляет основным потоком, потому что только основной поток имеет разрешение на обновление пользовательского интерфейса.

RootViewController.h

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController {

    //An array of dictionary objects
    NSArray *tweets;

    //A place to cache images
    NSDictionary *images;

    // the dispatch queue to load images
    dispatch_queue_t queue;
}

@property (nonatomic, retain) NSArray *tweets;
@property (nonatomic, retain) NSDictionary *images;

@end

RootViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = ...;
    //set up the cell
    ....
    cell.imageView.image = [self imageForRowAtIndexPath:indexPath];
    return cell;
}

- (UIImage *)imageForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // get the dictionary for the indexPath
    NSDictionary *tweet = ...;

    // get the user dictionary for the indexPath
    NSDictionary *user = [tweet objectForKey:@"user"];

    // get the user's id and check for a cached image first
    NSString *userID = [user objectForKey:@"id_str"];
    UIImage *image = [self.images objectForKey:userID];
    if(!image)
    {
        // if we didn't find an image, create a placeholder image and 
        // put it in the "cache". Start the download of the actual image
        image = [UIImage imageNamed:@"Placeholder.png"];
        [self.images setValue:image forKey:userID];

        //get the string version of the URL for the image
        NSString *url = [user objectForKey:@"profile_image_url"];

        // create the queue if it doesn't exist
        if (!queue) {
            queue = dispatch_queue_create("image_queue", NULL);
        }

        //dispatch_async to get the image data
        dispatch_async(queue, ^{

            NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
            UIImage *anImage = [UIImage imageWithData:data];
            [self.images setValue:anImage forKey:userID];
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

            //dispatch_async on the main queue to update the UI
            dispatch_async(dispatch_get_main_queue(), ^{
                cell.imageView.image = anImage;
            });
        });
    }

    // return the image, it could be the placeholder, or an image from the cache
    return image;
}
2 голосов
/ 31 января 2011

Расширьте NSOperation (что-то вроде ImageDownloadOperation) и добавьте операции загрузки в Global NSOperationQueue. Сделайте обратный вызов в ячейках табличного представления, которые устанавливают изображение после завершения загрузки. Извините, что нет примера кода, так как это будет большой объем пользовательского кода. Вот как я это сделал, проанализировав ссылки из объектов JSON.

...