UICollectionView: infinite scroll to the beginning of the collection view

I'm making collection view with a dynamic content loading ability. I want to make a calendar using UICollectionView. In my implementation, I create a data source array with dates. It shows only 4 weeks (current date in one of them). I also have 2 weeks before and 2 weeks after they are hidden (collection view visible size shows only 4 rows). In wanted to dynamically load previous/ next weeks if needed. But I have huge problems with collection view updates.

I want to made "infinite scroll" in both directions (up and down) that will show weeks with dates.


I used scrollViewDidScroll for detecting the moment when I need to update my data source array and reload cells.

I have huge lags on my iPhone 4S after method for updating collection view is called:


UIView.performWithoutAnimation { () -> Void in

  self.calendarCollectionView.performBatchUpdates({ () -> Void in
  self.calendarCollectionView.insertItemsAtIndexPaths(indexes)
}, completion: { (finish) -> Void in
})
}


I have tried this to load only previous dates, not next. I suspect that adding cells to the end of the collection view while scrolling would be okay. But adding it in the beggining of the collection view results in a huge visible lags.

As you can see, I used insertItemsAtIndexPaths, I also tried reloadData. Then I add performWithoutAnimation block, because thought that standard insert animation is a problem. I tried to made custom FlowLayout class, and implement animation by myself (e.g. turn all animation, I just want to see new items) it didn't help. I tried change tactics and not to add new cells, but reload old ones with new dates and set right content offset imulating infinite scroll.

I'm deadlocked. I thought this task is very trivial, but my solutions doesn't work. Looking for help / advice.


EDIT

Want to mention, that scrolling is very fast and I have no complaints on it. But just add reloading data and all ruined in lags.

You can see these spikes when I scroll the collection view on my device (and I if scroll more than offset constant set -> content reloaded contentOffset set to start offset, but, if I scroll fast, collectionview reloads more than one time). You can see single spike (one reload) and more of it. (I don't see image after posting the question, but see it in editing, if you don't see the image tell me please and I replace image with a link to it. Thanks.)

I see two ways, first: load a really big data to data source array and just scroll without frequent collection view reload. (Of course I need to do this at some point. For example if I initially add current year to the data source, I need to reload collecitonview (or add new cells) when I need to load next year).

Second way, is to reload data, but do not invalidate layout of the cells. I'm not sure how to do this, and would be appreciate if somebody gives me a clue.

To clarify, in fist way I think to insert cells, in the second I think to replace data source cell with new values.

Answered by the_schloss in 29084022

I'd suggest updating the data source directly instead. And do it on a background thread to keep the UI from getting locked up (that'll solve your lag problem).

That way, as you're scrolling, your delegate cellForItemAtIndexPath: call will return the proper cell without you having to go around that and force inserting rows.


It's much faster to update an array or dictionary on another thread and have the CollectionView update it's view on the main thread at the time it needs, than to force everything onto the main thread.


Also, although I haven't tested this: You should be able to update the data source, remove the beginning values, call reloadData on the CollectionView, and change the contentOffset all while it's still scrolling to give the illusion of infinite scrolling.

Accepted Answer

I'd suggest updating the data source directly instead. And do it on a background thread to keep the UI from getting locked up (that'll solve your lag problem).

That way, as you're scrolling, your delegate cellForItemAtIndexPath: call will return the proper cell without you having to go around that and force inserting rows.


It's much faster to update an array or dictionary on another thread and have the CollectionView update it's view on the main thread at the time it needs, than to force everything onto the main thread.


Also, although I haven't tested this: You should be able to update the data source, remove the beginning values, call reloadData on the CollectionView, and change the contentOffset all while it's still scrolling to give the illusion of infinite scrolling.

Thanks for response, I also come to this solution and prototyping it right now. To clarify, you suggest to update data souce itself without increasing it's length and for example after updating data source, scroll my table view to the cells that wasn't visible and they will be loaded with new data source values, but I don't need to call reloadData explicitly, right?


I don't get the last part: "remove the beginning values, call reloadData on the CollectionView". Why I need to call reloadData, I want to avoid it. Did you mean to use another approach to that I describe below, that include usign reloadData?

Thanks for reply.

It's not clear from your description whether it's the infinite scrolling or some other aspect that's a problem for your scenario. If it's infinite scrolling, I suggest you watch the WWDC video about it:


https://developer.apple.com/videos/wwdc/2011/


Note that this video is one of a "series" that continued from year to year by the same 2 presenters, and it's worth watching all of them.


Note also that this spans enough time that APIs have changed significantly, so some of the solutions presented may now be available in the frameworks, or need to be modified for current iOS versions. However the thought process demonstrated in these videos is extremely enlightening, so they're probably worth watching regardless.

Thanks for reply, yes, I'm talking about infinite scrolling, and already made a prototype that works as I want as far as I play with it 🙂. Didn't watch exactly that video (it's opened in my Safary tab for few days).

Hi Alexander,

I faced with the same problem. Please, can U give an example of the solution?

Thanks,

Yauheni.

UICollectionView: infinite scroll to the beginning of the collection view
 
 
Q