2

我有一个 iOS 应用程序,它有一个 UITableView 和包含 UIImageView 的自定义 TableViewCells。该图像是从 Web 服务加载的,因此在初始加载期间,我会显示一个“正在加载”的图像,然后使用 gcd 调度并获取与该单元格的数据匹配的图像。

当我使用 DISPATCH_QUEUE_PRIORITY_HIGH 全局队列来执行图像提取时,我偶尔会在 tableview 单元格中加载错误的图像。如果我使用自己的自定义队列,那么正确的图像会填充到单元格中,但 tableview 性能很糟糕。

这是代码...

    // See if the icon is in the cache
if([self.photoCache objectForKey:[sample valueForKey:@"api_id"]]){
    [[cell sampleIcon]setImage:[self.photoCache objectForKey:[sample valueForKey:@"api_id"]]];
}
else {
    NSLog(@"Cache miss");
        [cell.sampleIcon setImage:nil];
        dispatch_queue_t cacheMissQueue = dispatch_queue_create("cacheMissQueue", NULL);
        //dispatch_queue_t cacheMissQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
        dispatch_async(cacheMissQueue, ^{
            if(sample.thumbnailFilename && sample.api_id){
                NSData *thumbNailData = [[NSData alloc] initWithContentsOfFile:sample.thumbnailFilename];
                UIImage *thumbNailImage = [[UIImage alloc]initWithData:thumbNailData];
                if(thumbNailImage){
                    // Set the cell
                    dispatch_sync(dispatch_get_main_queue(), ^{
                        [[cell sampleIcon]setImage:thumbNailImage];
                        [cell setNeedsLayout];
                    });
                    // save it to cache for future references
                    NSLog(@"DEBUG: Saving to cache %@ for sample %@",sample.thumbnailFilename,[sample objectID]);
                    [self.photoCache setObject:thumbNailImage forKey:sample.api_id];
                }
            }
        });
        dispatch_release(cacheMissQueue);
}
4

2 回答 2

1

观看 WWDC 2012 会议 #211 帮助很大,我将代码从使用 GCD 更改为 NSOperationQueue 并解决了问题。

新代码...

[[self imgQueue]addOperationWithBlock:^{
            if(sample.thumbnailFilename && sample.api_id){
                NSData *thumbNailData = [[NSData alloc] initWithContentsOfFile:sample.thumbnailFilename];
                UIImage *thumbNailImage = [[UIImage alloc]initWithData:thumbNailData];
                if(thumbNailImage){
                    // Set the cell
                    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                        [[cell sampleIcon]setImage:thumbNailImage];
                        [cell setNeedsLayout];
                    }];
                    // save it to cache for future references
                    [self.photoCache setObject:thumbNailImage forKey:sample.api_id];
                }
            }

        }];
于 2012-08-09T02:49:21.493 回答
0

当你最终得到一个图像时,你需要在单元格的 indexPath 和图像之间建立一个关联。由于这是在后台线程上,我建议你做的是使用一个块向 mainQueue 发布一个通知,表明这样的图像可用。仅在主线程上,您向 tableView 询问可见单元格的数组,如果您有图像的单元格正在显示,那么您可以在那时直接设置图像(您在主线程上,您知道单元格在那里并且正在显示,并且对于此运行循环迭代它不会改变。)如果单元格未显示,没问题,下次该单元格进入范围时,您将有图像等待它。我现在正在我的应用程序中执行此操作,它已经发布了好几个月,并且一切正常,并且在响应性方面获得了好评(就像您的应用程序一样,如果您这样做!)

于 2012-08-03T18:07:17.873 回答