如何告诉 UICollectionView 预加载更大范围的单元格?

Posted

技术标签:

【中文标题】如何告诉 UICollectionView 预加载更大范围的单元格?【英文标题】:How to tell UICollectionView to preload a larger range of cells? 【发布时间】:2013-10-01 21:02:15 【问题描述】:

我有一个 UICollectionView,它显示从网络检索到的图像。它们是异步下载的。

当用户快速滚动时,他们会看到占位符,直到单元格加载。似乎 UICollectionView 只加载可见的内容。

有没有办法说“集合视图,在上方和下方多加载 20 个单元格”,以便在用户查看内容而不滚动时加载更多单元格的机会更高?

【问题讨论】:

我能想到的一种方法是使 UICollectionView 大于其实际可视部分(隐藏在某个掩码下)。但这绝对不是最佳解决方案:) 但是由于您的数据是异步加载的:可能不是collectionview而是dataSource问题... 你的收藏中有多少图像,因为如果你同时加载所有图像,你可能会收到内存警告 这不是UICollectionView应该负责解决的问题。它会立即加载单元格,但您希望您的模型在加载时更加准备好。编写 VC 代码,询问你的模型下一个或最后 N 个 url,然后开始获取这些,缓存结果。 @rokjarc 不,UICollectionView 仅从数据源请求 10 个单元格,但是当用户开始滚动时它会继续请求更多单元格。它应该只在用户不滚动时预加载更多单元格。 【参考方案1】:

这个想法是让 VC 识别何时可能需要远程加载并启动它。唯一棘手的部分是保持正确的状态,以免触发太多。

假设你的收藏是垂直的,你想知道的条件是:

BOOL topLoad = scrollView.contentOffset.y < M * scrollView.bounds.size.height

或何时

BOOL bottomLoad = scrollView.contentOffset.y > scrollView.contentSize.height - M * scrollView.bounds.size.height

换句话说,当我们距离内容边缘有 M 个“页面”时。但在实践中,这种情况会被过度触发,比如当你第一次加载时,或者如果你在 scrollViewDidScroll 上测试它,你不想为用户滚动的每个像素生成 Web 请求。

因此,正确处理需要在视图控制器中添加额外的状态。 vc 可以有一对 BOOL,如 topLoadEnabled、bottomLoadEnabled,在视图准备好之前为 NO。然后,滚动委托代码如下所示:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 

    // compute topLoad and bottomLoad conditions
    if (topLoad && self.topLoadEnabled) [self startTopLoad];

底部也类似。加载代码抽象地看起来像这样:

self.topLoadEnabled = NO;  // don't trigger more loading until we're done
[self.model getMoreTopStuff:^(NSArray *newStuff, NSError *error) 

    // do view inserts, e.g. tableView.beginUpdates
    self.topLoadEnabled = YES;
];

底部的想法相同。我们希望模型自己获取(也许模型有图像 url)并缓存结果(然后模型有图像)。作为视图的数据源,视图控制器被调用来配置视图单元。我可以天真地向模型询问图像。模型应该回答获取的图像或占位符。

希望这是有道理的。

【讨论】:

【参考方案2】:

在我看来,您做出了错误的假设:单元格只是视图,因此您不应将它们视为模型对象。 UICollectionView 和 UITableView 非常高效,因为它们不断回收单元格,因此您应该考虑在业务方面预加载内容。创建交互器或视图模型对象并使用它们填充您的数据源,然后如果您仍然希望这样做,您将能够要求这些对象预加载图像。

【讨论】:

【参考方案3】:

一个 BOOL 标志很少是答案。我宁愿去估计一个合理的页面大小并根据需要从cellForItemAtIndePath 方法中获取图像。

【讨论】:

以上是关于如何告诉 UICollectionView 预加载更大范围的单元格?的主要内容,如果未能解决你的问题,请参考以下文章

预加载下一个(当前不可见)单元格 UICollectionView

uicollectionview 中的延迟加载

如何使用 UICollectionView 选择要预取的项目数?

uicollectionview 在底部滚动加载更多数据。 iOS 斯威夫特

如何在 AS3 中创建预加载器

如何在 HTML 5 中为音频、视频、css、图像创建预加载器?