UITableView与缓存异步加载缩略图图像

时间:2012-04-14 17:53:14

标签: ios uitableview grand-central-dispatch

我正在尝试将远程站点的缩略图加载到UITableView上。我想以异步方式执行此操作,并且我想为缩略图图像实现穷人的缓存。这是我的代码片段(我将在下面描述有问题的行为):

@property (nonatomic, strong) NSMutableDictionary *thumbnailsCache;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

// ...after obtaining the cell:

NSString *thumbnailCacheKey = [NSString stringWithFormat:@"cache%d", indexPath.row];

if (![[self.thumbnailsCache allKeys] containsObject:thumbnailCacheKey]) {

    // thumbnail for this row is not found in cache, so get it from remote website
    __block NSData *image = nil;        
    dispatch_queue_t imageQueue = dispatch_queue_create("queueForCellImage", NULL);
    dispatch_async(imageQueue, ^{
        NSString *thumbnailURL = myCustomFunctionGetThumbnailURL:indexPath.row;
        image = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:thumbnailURL]];
        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = [UIImage imageWithData:image];
        });
    });
    dispatch_release(imageQueue);
    [self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];

} else {

    // thumbnail is in cache
    NSData *image = [self.thumbnailsCache objectForKey:thumbnailCacheKey];
    dispatch_async(dispatch_get_main_queue(), ^{
        cell.imageView.image = [UIImage imageWithData:image];
    });

}

所以这是有问题的行为:

  1. 加载UITableView时,缩略图不会显示在初始单元格集上。只有当一个单元格移出屏幕后,才会重新开启缩略图显示。

  2. 缓存根本不起作用。据我所知,它无法将缩略图完全保存到缓存中。也就是说,这一行失败了:

    [self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];

  3. 为每个单元格创建/释放GCD队列。此外,队列名称每次都相同。这是不好的做法吗?

  4. 我很感激你们指出你看到的任何错误,甚至任何一般的方法评论。感谢。

    更新

    1. 已解决:我添加了对reloadRowsAtIndexPaths的调用,现在缩略图图像加载到显示的初始行

    2. 已解决:失败的原因是因为它在另一个线程完成设置该对象之前将图像对象添加到字典中。我创建了一个实例方法来将对象添加到属性字典中,这样我就可以从块内部调用它,确保在设置图像对象后添加它。

2 个答案:

答案 0 :(得分:3)

你应该明确地看一下SDWebImage。 这正是你要找的东西。 SDWebImage也非常快,可以使用多核CPU。

答案 1 :(得分:1)

1)没有显示初始图像的原因是因为单元格使用image = nil进行渲染,因此它会智能地隐藏图像视图。

2)你是否试过在你的街区内移动这条线?

[self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];

3)这只是一种区分队列以进行调试,并从控制台获取信息的方法,如果您的应用程序崩溃,那么您可以看到队列的名称。这不应该是您具有相同名称的问题,因为它执行相同的操作。如果您具有相同的逻辑,则不希望在另一个表视图中使用此名称。