如何异步下载大量图像并将它们放在tableView单元格imageView中

时间:2011-01-31 20:51:21

标签: objective-c xml ios4 asynchronous rss

我想知道如何异步下载大量图像(通过xml解析链接)并将它们放在tableView的单元格中。我试过MarkJ的教程,除了我希望它们在单元格的imageView中显示之外,它完美地运行了。如果你能告诉我如何做到这一点会很棒。

2 个答案:

答案 0 :(得分:3)

我有类似的情况,但我的数据格式是JSON而不是xml。下载和异步部分应该非常相似。我决定尝试使用Objective-C块和GCD的dispatch_async方法。我的代码的重要部分如下所示,遗漏了一些不需要的细节。

我有一个用于缓存图像的NSDictionary,称为图像。第一步是检查我是否有当前NSIndexPath的图像。如果是这样,我只是返回该图像。如果没有,我创建一个占位符图像,开始下载真实图像,并返回占位符。

“开始下载真实图像”部分,包括检查我想要使用的队列是否已经存在,以及是否创建它。然后我在后台线程上对NSData的便捷方法dataWithContentsOfURL进行异步调用。这是一个阻塞调用,但它在后台线程上,因此UI保持响应。当调用返回时,我从数据中创建UIImage,缓存图像,并检索indexPath的单元格。然后我再做一个dispatch_async调用,它只是在单元格上设置imageView.image属性。这里的关键是使用dispatch_get_main_queue()来获取对管理主线程的队列的引用,因为只有主线程才有权更新UI。

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;
}

答案 1 :(得分:2)

扩展NSOperation(类似于ImageDownloadOperation)并将下载操作添加到Global NSOperationQueue。在表格视图上进行回调,在下载完成时设置图像。对不起,没有代码示例,因为它将是大量的自定义代码。这就是我用JSON对象解析的链接的方法。