How to tell UICollectionView to preload a larger range of cells?

I have a UICollectionView which shows images retrieved from the web. They are downloaded asynchronous.

When user scrolls fast, they see placeholders until the cell loads. It seems UICollectionView only loads what is visible.

Is there a way to say "collection view, load 20 cells more above and below" so chance is higher that it loaded more cells while user was looking at content without scrolling?


The idea is to have the VC recognize when a remote load might be required and start it. The only tricky part is keeping the right state so you don't trigger too much.

Let's say your collection is vertical, the condition you want to know about is when:

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

or when

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

in other words, when we are M "pages" from the edge of the content. In practice though, this condition will be over-triggered, like when you're first loading, or if you're testing it on scrollViewDidScroll , you don't want to generate web requests for every pixel of user scrolling.

Getting it right, therefore, requires additional state in the view controller. The vc can have a pair of BOOLs, like topLoadEnabled, bottomLoadEnabled, that are NO until the view is ready. Then, scroll delegate code looks like this:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

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

similarly for bottom. The load code looks like this, abstractly:

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;
}];

Same idea for bottom. We expect the model to fetch for itself (maybe the model has image urls) and cache the result (then the model has images). As the datasource for the view, the view controller gets called upon to configure view cells. I can just naively ask the model for images. The model should answer either fetched images or placeholders.

Hope that makes sense.


In my opinion you are making the wrong assumption: cells are just views so you shouldn't treat them as model objects. UICollectionView and UITableView are very efficient because they constantly recycle cells so you should think in therms of pre loading content in the business side of things. Create interactor or viewmodel objects and populate your data source with those, then you'll be able to ask those objects to preload images, if you still wish to do so.


A BOOL flag seldom is the answer. I'd rather go for estimating a reasonable page size and fetching images as needed from the cellForItemAtIndePath method.

链接地址: http://www.djcxy.com/p/16320.html

上一篇: 如何正确地管理每个视图控制器中的NSManagedObjectContext?

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