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

8

我有一个UICollectionView,展示从网络上获取的图片。它们是异步下载的。

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

是否有一种方法可以让“集合视图,在上下各加载20个单元格”,这样在用户查看内容而不滚动时,更有可能加载更多的单元格?


我能想到的一种方法是使UICollectionView比其实际可见部分更大(隐藏在某些遮罩下)。但这绝对不是最优解 :) - Rok Jarc
但由于您的数据是异步加载的:也许问题不在集合视图,而在于数据源... - Rok Jarc
你的收藏中有多少张图片?因为如果同时加载所有图片,可能会出现内存警告。 - Mirko Catalano
3
UICollectionView不应该负责解决这个问题。尽管它能够快速加载单元格,但您希望在加载之前模型准备好更多数据。编写VC代码,请求您的模型提供下一个或最后N个URL,并开始获取和缓存结果。 - danh
@rokjarc 不,UICollectionView 仅从数据源请求10个单元格,但当用户开始滚动时,它会继续请求更多。它应该在用户不滚动时预加载更多单元格。 - openfrog
@danh 当它收到滚动完成的回调时,它会告诉数据源预加载更多单元格吗?请将此作为答案,我会接受。 - openfrog
3个回答

2

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


2

这个想法是让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)并缓存结果(然后模型就有了图像)。作为视图的数据源,视图控制器被调用来配置视图单元格。我可以简单地向模型请求图像。模型应该回答已获取的图像或占位符。
希望这样说得通。

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接