I have a UICollectionView
using a standard UICollectionViewFlowLayout
with an estimatedItemSize
set to UICollectionViewFlowLayoutAutomaticSize
.
Once I call collectionView.reloadData()
the scroll position of the view resets to CGPoint(x: 0, y: 0)
. I know that .reloadData()
should only be used as a last resort, it is necessary in my scenario though. I have found out so far that it is probably caused by not returning an item size through collectionView(_:layout:sizeForItemAt:)
. (Any solutions for that analogous to UITableView
’s tableView:estimatedHeightForRowAtIndexPath:
like in this StackOverflow answer would be highly appreciated).
reloadData
reloads all cells in your UICollectionView
so if you have any reference to cells it will point to object that is not exist, and what's more if it's strong reference it may cause a retain cycle. So:
You should not do it!
But...
It's hard to imagine the scenario where reloadData
is needed and it cannot be replaced by inserting and deleting objects.
So what you may want to use is reload single row or maybe insert items that it change in your data model. You didn't post what your problem is with details, but you can do any of this actions mentioned earlier like:
collectionView.performBatchUpdates({
collectionView.insertItems(at: <#T##[IndexPath]#>)
collectionView.deleteItems(at: <#T##[IndexPath]#>)
collectionView.reloadItems(at: <#T##[IndexPath]#>)
}, completion: { (<#Bool#>) in
<#code#>
})
But make sure you'll edit your data model first. So:
var dataModel: [String] = ["0","1","2"] //Data model for Collection View
collectionView.reloadData() // In that point you will have 3 cells visible on the sceen
.
.
.
dataModel.removeFirst() // now your data model is ["1","2"]
collectionView.performBatchUpdates({
collectionView.deleteItems(at: [IndexPath(row: 0, section:0)])
}, completion: { success in
//some check consistency code
})
And with that, your collectionview will remain the same, and no other change will be made besides this first row.
Not sure if it might work, but you can give a try :
let currentOffset = self.collectionView.contentOffset
self.collectionView.reloadData()
self.collectionView.setContentOffset(currentOffset, animated: false)
Do lemme know. Thanks :)