使用GCD填充TableView单元格

时间:2011-06-29 16:29:15

标签: iphone objective-c ios xcode grand-central-dispatch

我刚接触GCD工作,我很难理解我在这里做的事情是否正确。

当我配置一个单元格时,我想从托管对象中提取一个URL,然后将一个块发送到GCD以下拉驻留在该URL的缩略图图像。

图像下载后,我将在第一个块中调度另一个块,将下载的缩略图放入单元格中。

当表格显示在屏幕上时,我希望在每个单元格的缩略图中看到一个活动微调器,缩略图随后会在完成下载后替换为实际图像。

实际发生的是,单元格出现在TableView中,我看不到微调器。但是,如果我单击一个单元格,图像会突然出现。同样,如果我离开该视图然后再次显示它。另外,当我向上和向下滚动TableView时,会发生一些非常奇怪的事情 - 缩略图似乎“重复”然后在我滚动时重新下载。

我很抱歉,如果这有点难以解释,但我不知道如何最好地描述我所看到的。

如果有人可以查看代码并且可能就可能出现的问题提出一些建议,我会很感激:

 if([managedObject isKindOfClass:[Photo class]])
{
    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

    [cell.imageView addSubview:spinner];
    [spinner startAnimating];

    Photo *photo = (Photo *)managedObject;

    NSString *URLString = photo.thumbnailURL;

    dispatch_queue_t callerQueue = dispatch_get_current_queue();
    dispatch_queue_t downloadQueue = dispatch_queue_create("Thumb downloader", NULL);

    dispatch_async(downloadQueue, ^{
       NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:URLString];  
        dispatch_async(callerQueue, ^{
            UIImage *thumbImage = [UIImage imageWithData:imageData];
            [spinner stopAnimating];
            cell.imageView.image = thumbImage;
            [cell.imageView setNeedsDisplay];
        });
    });
    dispatch_release(downloadQueue);
}
return cell;

2 个答案:

答案 0 :(得分:4)

在后台加载数据后(在本例中为图像),您不应直接访问单元格。如果在加载数据之前滚动屏幕,则它无效。您应该在数据加载方式上设置机制,并在它返回时调用[tableView reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation]

答案 1 :(得分:1)

  

[cell.imageView addSubview:spinner];

上面的线条闻起来不像它会起作用。请尝试[cell.contentView addSubview:spinner];。您可能需要更改微调器的frame.origin才能将其放在正确的位置。

  

缩略图似乎“重复”,然后在滚动时重新下载。

由于您的tableViewCells正在被重用,因此下载的图像与原始获取请求的单元格不匹配。

在内部,内部块中,您需要验证单元格是否仍然对应于您认为的托管对象/照片/索引路径。

其他:

  • 你的微调器正在泄漏记忆。
  • [spinner stopAnimating]之后您可能需要[spinner removeFromSuperview]