【问题标题】:UITableViewCell image async queue caching not working properlyUITableViewCell 图像异步队列缓存无法正常工作
【发布时间】:2014-02-24 19:36:08
【问题描述】:

谁能告诉我我的代码有什么问题。它似乎有效,但是当我快速滚动然后停止时,UIImageView 在显示正确的图片之前循环浏览几张图片。这发生得很快但很明显。

if (![post objectForKey:@"photoData"] && ![post objectForKey:@"isDownloadingPhoto"]){
    cell.instagramPhoto.image = nil;
    [[combinedArray objectAtIndex:indexPath.row] setObject:@"loading" forKey:@"photoData"];
    [[combinedArray objectAtIndex:indexPath.row] setObject:@"yes" forKey:@"isDownloadingPhoto"];
    [cell.instagramPhoto setAlpha:0];
    if (instagramURL != nil){
        dispatch_async(kBgQueue, ^{
            int index = indexPath.row;
            NSData* data = [NSData dataWithContentsOfURL: instagramURL];
            if (data.length > 0){
                [[combinedArray objectAtIndex:index] setObject:data forKey:@"photoData"];
                [[combinedArray objectAtIndex:index] setObject:@"no" forKey:@"isDownloadingPhoto"];
                UIImage *image = [UIImage imageWithData:data];
                dispatch_sync(dispatch_get_main_queue(), ^{
                    cell.instagramPhoto.image = image;
                    [UIView beginAnimations:nil context:NULL];
                    [UIView setAnimationBeginsFromCurrentState:YES];
                    [UIView setAnimationDuration:0.4f];
                    cell.instagramPhoto.alpha = 1.0;
                    [UIView commitAnimations];
                });
            }
        });
    }
}
else if ([[post valueForKey:@"isDownloadingPhoto"] isEqualToString:@"yes"]) {
    NSLog(@"loading");
    cell.instagramPhoto.image = nil;
}
else {
    NSData *data = [post valueForKey:@"photoData"];
    NSLog(@"saved");
    UIImage *image = [UIImage imageWithData:data];
    cell.instagramPhoto.image = image;
}

【问题讨论】:

  • 所有这些都在cellForIndexPath?
  • 是的,都在 cellForRowIndexPath 内
  • 而且你在 presumable 中也有一些单元重用逻辑。我怀疑这是正在发生的事情 - cellForIndex... 被调用一个单元格,你开始异步下载过程,滚动表格视图,这个单元格在另一个 cellForIndex 中被重用
  • 有什么办法可以避免这种情况吗?如果不是,在 tableviewCell 中缓存图像的推荐方法是什么?
  • 让我把它包装成一个答案

标签: ios objective-c uitableview caching asynchronous


【解决方案1】:

看起来这段代码是在tableView:cellForRowAtIndexPath 中执行的。如果您在此处有任何单元重用逻辑 - 您可能会遇到问题,在当前异步图像下载操作完成之前重用单元时。

如果单元格在完成之前被重复使用,您需要能够中止这些下载任务。

** 更新 **

有几种方法可以实现它:

  • 最简单的一个(可能也是最消耗内存的) - 确保为每个单元生成唯一的 cellId,这样就不会重复使用已分配的单元。它会更慢,但您可以保证您启动的操作将在您启动它的同一单元格上完成。

  • 下载完成后检查单元格是否相同。例如,您可以在代码开头将单元格的 tag 分配给其行号。

    cell.tag = indexPath.row

然后在开始dataWithContext调用之前将其保存并在之后检查。

int oldTag = cell.tag;
dataWithContext...
if (cell.tag != oldTag) {
   // Don't so any image update
}
  • 将 dataWithContext 更改为异步内容,这样您就可以真正中断和中止下载过程。我不知道如何继续这个 - 这需要更多的研究。

【讨论】:

  • 我完全不知道如何在下载完成之前检测单元格是否被重用。您对如何实现这一点有任何想法吗?
  • 这很容易。子类UITableViewCell 并在您的类中定义ready 属性。在异步下载完成后将该属性设置为 YES。
  • 对不起,我不认为我理解正确。这样做与从异步设置图像不一样吗?
  • 您也可以使用图像属性(无论是否为 nil)。主要问题应该是 - 从我的角度来看如何中止下载任务。
  • 这是我的问题,ready 属性如何让我中止下载?
猜你喜欢
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多