我有一个UICollectionView,展示从网络上获取的图片。它们是异步下载的。
当用户快速滚动时,他们会看到占位符,直到单元格加载完毕。似乎UICollectionView只加载可见的内容。
是否有一种方法可以让“集合视图,在上下各加载20个单元格”,这样在用户查看内容而不滚动时,更有可能加载更多的单元格?
我有一个UICollectionView,展示从网络上获取的图片。它们是异步下载的。
当用户快速滚动时,他们会看到占位符,直到单元格加载完毕。似乎UICollectionView只加载可见的内容。
是否有一种方法可以让“集合视图,在上下各加载20个单元格”,这样在用户查看内容而不滚动时,更有可能加载更多的单元格?
在我看来,你所做的错误假设是:单元格只是视图,因此你不应该将它们视为模型对象。UICollectionView和UITableView非常高效,因为它们不断地回收单元格,因此你应该从业务角度考虑预加载内容。创建互动器或视图模型对象,并使用它们填充数据源,然后即可要求这些对象预加载图像(如果你仍然希望这样做)。
这个想法是让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;
}];
一个BOOL标志很少是答案。我宁愿估计一个合理的页面大小,并从cellForItemAtIndePath
方法中根据需要获取图像。