Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy loading technique for UICollectionView

Tags:

objective-c

I have an IOS application, which uses a UICollectionView for displaying a horizontal grid of cells. All i need, is a clever way of (lazy) loading data when the user reaches the end of my UICollectionView. The code i use now is :

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    GridCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:Cell forIndexPath:indexPath];


    /**
     TODO
     - Find a good way to check if the user has reach the end of the grid
     - This next piece of code is for demonstration purposes. A real check has to be
     done yet!!!
     **/

    // releases is my datasource //

    if(indexPath.row == (releases.count - 1)) {
        [self getNextListData];
    }

    return cell; // <-- finally return the cell


}

The problem with this code is : if a user scrolls really fast to the end, he has to scroll back and forth to load more items. This is really not user friendly and i need a better way to load items when needed.

Does anyone have any suggestions?

Thanks in advance.

like image 941
Jack Sierkstra Avatar asked Mar 23 '13 17:03

Jack Sierkstra


2 Answers

UICollectionView inherits from UIScrollView. UIScrollView has a delegate, UIScrollViewDelegate that has a bunch of methods related to scrolling. In one of these delegate methods (such as scrollViewDidBeginDecelerating:), you can check to see how far along the page you are, with the contentOffset and contentSize properties. If you're close to the end (defined by whatever % is the end for you), fetch more data.

An advantage to using a scrollview method is that it will not cause collectionView:cellForItemAtIndexPath: to be slower (by forcing it to run code for every collectionview unnecessarily).

This is basically the same technique that Apple suggests for lazy-loading of UITableView data's, applied slightly differently. They have some sample code for that as well (such as LazyTableImages)

like image 107
zadr Avatar answered Sep 29 '22 18:09

zadr


When I ran into this problem with table views, I had to do some user testing. I found that if I started my load 10 cells before the end of the table, the new cell should be ready. Assuming that you are doing background loading of the data, that is.

if (indexPath.row >= [releases count] - 10)
    [self getNextListData];

You would want to do some testing to see what number works for you.

In addition, I also had a loading indicator cell. In my number of rows in section callback, I always returned 1 extra.

return [releases count] + 1;

At the start of my cell for row callback I returned a special loading indicator cell.

if (indexPath.row == [releases count])
    return [JLTActivityCell sharedInstance];

I'm not sure exactly how that advice will apply to collection views, but hopefully it gets you pointed in a good direction.

like image 29
Jeffery Thomas Avatar answered Sep 29 '22 18:09

Jeffery Thomas