It looks like you're doing a whole lotta stuff that doesn't need to be (and shouldn't be) done.
Couple examples...
1 - You're overriding intrinsicContentSize
and contentSize
, and calling layout funcs at the same time. But... you have set a size for your collection view via constraints. So, intrinsicContentSize
has no effect, but the funcs you're calling in contentSize
may be causing issues.
2 - You're setting flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
and returning .init(width: 1, height: 1)
for sizeForItemAt
... you should use a reasonable estimated size, and not implement sizeForItemAt
.
3 - There is no need to reloadData()
to update the appearance of the selected cell... Collection Views track the selected cell(s) for us. It's easier to override var isSelected: Bool
in the cell class. Unless...
4 - You are repeatedly calling reloadData()
. When you reloadData()
, you are telling the collection view to de-select any selected cells.
I put up a modification to your repo here: https://github.com/DonMag/CollectionViewSelfSizingIssue
Edit - After comments...
OK - the intrinsicContentSize
implementation is there to allow the collection view to be centered when we have only a few items. That appears to work fine.
The reason the collection is getting "shifted back to the start" on reloadData()
is due to this:
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: 1, height: 1)
}
I'm not an Apple engineer, but as I understand it (and this can be confirmed with some debug print()
statements):
- on
reloadData()
, the collection view calls sizeForItemAt
for every item in the data set
- the collection view then starts laying out the cells
if we do this:
items = (0..<150).map { "\($0)" }
sizeForItemAt
will be called 150 times before the first call to cellForItemAt
.
So, if we have 10 items, and we're returning a width of 1
for every cell, the collection view thinks:
10 * 1 == 10
9 * 5 == 45 // 9 5-point inter-item spaces
------------
Total collection view width will be 55-points
And, naturally, it shifts back to starting with cell 0
, because all 10 cells are going to fit.
I've updated my repo to allow both collection views to "center themselves" when there are only a few items.