【问题标题】:UICollectionView loading cell data in wrong placesUICollectionView 在错误的地方加载单元格数据
【发布时间】:2014-12-31 12:27:05
【问题描述】:

我有一个 UICollectionView 显示自定义单元格的网格。当我在cellForItemAtIndexPath 中设置单元格时,我会调用单元格子类上的一个方法来设置 UI(例如[cell setupUI])。此方法会加载一些标签,但也会调用从 Web 获取图像的异步方法。我正在使用 AFNetworking 来处理这个问题。

我的问题是,有时(经常)图像会加载到正确的单元格 + 不应该设置图像的单元格中。数据似乎只是随机加载到单元格中。

我已经研究了一段时间并尝试了多种方法,但我无法弄清楚我哪里出错了。有没有我遗漏的问题?

注意:我已经检查过,设置这些图像单元格的方法被称为正确的次数 (3),但图像出现在 5 个单元格上。

编辑

这是用于获取图像的代码。我以前在没有 CollectionView 的情况下使用过它(自己绘制网格)并且效果很好:

  [self.youtubeThumbnail setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
        weakImageView.image = image;
 } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){

 }];

weakImageView 是对我的单元格图像视图的弱引用。以上代码在cell子类中,从cellForItemAtIndexPath中调用。

我应该指出这个方法在 dispatch_async(dispatch_get_global_queue) 上运行,图像加载在 dispatch_async(dispatch_get_main_queue) 上。

解决方案

所以我的问题其实很奇怪。我的集合视图被多次重新加载,这导致数据多次出现在不正确的单元格中。我仍然不能 100% 确定为什么会这样,但我已经设法通过检查内容是否已重新加载、设置 BOOL 并防止再次重新加载来解决它。 我选择的答案是正确的,这有助于我获得正确的异步加载,这也可能是问题的一部分。 感谢您的帮助。

【问题讨论】:

  • 您可以将代码发布到您要获取图像的位置吗?它可能就像 reloadData 在错误的位置或获取问题一样简单。另外,为了排查和排除错误假设,请尝试在应用启动时下载图像数组,以便将其存储在本地。
  • @carlodurso 我添加了获取图像的代码和更多解释。
  • 我应该指出这个方法是在 dispatch_async(dispatch_get_global_queue) 上运行的并且图像加载是在 dispatch_async(dispatch_get_main_queue) 上。

标签: ios objective-c uicollectionview


【解决方案1】:

问题可能与单元重用有关(尽管没有提供代码,我只是在猜测)。当您滚动浏览集合视图时,屏幕上显示的单元格会被回收,然后再重复使用以避免滚动时必须创建大量对象的开销。 UICollectionView 类参考中有更多信息。

更具体地说,您看到的问题很可能是当您的网络响应下降时,最初创建请求的单元格不在屏幕上。您可以按照 Apple 的旧 LazyTableImages 示例应用程序来解决此问题。关键在于RootViewController中startIconDownload:forIndexPath:的实现。

[iconDownloader setCompletionHandler:^{

        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

        // Display the newly loaded image
        cell.imageView.image = appRecord.appIcon;

        // Remove the IconDownloader from the in progress list.
        // This will result in it being deallocated.
        [self.imageDownloadsInProgress removeObjectForKey:indexPath];

    }];

所以当图像完成下载时,表格视图将正确的单元格发送到设置 imageView 的完成块。因此,您将拥有正确的 Table View Cell 或(或在您的情况下为 Collection View Cell)。而且,如果单元格触发了一个请求,但在它下降之前被滚动到屏幕外,那么您无需担心,因为 TableView/CollectionView 方法将为屏幕外单元格返回 nil。

【讨论】:

  • 我想我必须在视图控制器而不是单元子类上运行这段代码?
  • 当然。您应该完全避免将任何代码放入您的单元子类中。想想 MVC - 在某些模型(在本例中为 Internet)和您的视图(表格视图单元格、表格视图)之间分配视图控制器。视图不应该直接做这项工作。
  • 好的,谢谢。我现在正在尝试这个。该方法被调用了正确的次数,但单元格 UI 没有更新。
  • 现在调试它 - 看起来检索到的单元格是 nil。
  • 奇怪的是 cellForItemAtIndexPath: 正在返回一个零单元对象。我检查了一下,集合视图有 8 个单元格。我尝试获取 0、1 和 2,但每次只得到 nil。
【解决方案2】:

如果您愿意使用任何第三方库,我建议您查看SDWebImage。解决了异步下载内容时不正确单元格的数据不正确的问题。

它的代码是这样的:

[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

它使用简单的方法扩展 UIImageView 以轻松让您的收藏拥有并保持正确的图像。这也适用于标准 UITableViewCells。

【讨论】:

  • 这与 AFNetworking 有什么不同,它给了我类似的方法吗? (setImageWithURLRequest: placeholderImage: 成功:)
  • 我不确定每个的内部实现是什么。我从来没有像使用 SDWebImage 那样使用 AFNetworking 下载图像。随意尝试两者并告诉我们!
  • 谢谢。我的理解是他们做同样的事情(我在选择 AFNetworking 之前查看了几个第三方库)但我一定会尝试一下。
猜你喜欢
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 2013-04-27
  • 1970-01-01
相关资源
最近更新 更多