5

我正在尝试将缩略图从远程站点加载到 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 队列。此外,队列名称每次都相同。这是不好的做法吗?

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

更新:

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

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

4

2 回答 2

3

您应该明确地看看SDWebImage。这正是您要寻找的。SDWebImage 也非常快,可以使用多核 CPU。

于 2012-04-14T18:10:32.150 回答
1

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

2)你有没有尝试在你的街区内移动这条线?

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

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

于 2012-04-14T17:58:31.320 回答