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.
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.