iosswiftuicollectionviewuicollectionviewcelluicollectionviewflowlayout

In iOS 12, when UICollectionView is created using Self Sizing cells with constraints, upon reload layout has wrong height until I scroll


I have a weird issue in iOS 12 when using solution as explained here.

It works great when collection view loads for first time, however when I try to reload the collection view using either collectionView.reloadData() or collectionView.collectionViewLayout.invalidateLayout(), a weird height to cell is added.

Once I start scrolling everything will be normal again. Please see images below. First image shows working heights for cells after view loads. Second one shows cells after reload is pressed.

Works great at first load

After clicking on reload bar button

The reload bar button calls following method.

@objc func reloadCollectionView() {
        collectionView.collectionViewLayout.invalidateLayout()
}

Please view sample project in GitHub here for reproducing the issue. I used Xcode 10.1 and 10.2 to reproduce the issue.

Any kind of help or direction for resolving the issue would be highly appreciated!

Thanks in advance.


Solution

  • I think the issue is coming from you calling:

    flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    

    in your project.

    If you reset this to something like:

    layoutFlow.estimatedItemSize = CGSize(width: UIScreen.main.bounds.size.width, height: 100)
    

    Then it immediately runs smoother.

    Note: It is worth noting that the estimated height you set your cells to matters. If you set it to 0 then reloadData() will scroll the collectionView to the top. Setting an accurate value seems to work best in testing

    There are still a few bugs which seem to be fixed by removing the

    collectionView.collectionViewLayout.invalidateLayout()
    

    and swapping it for something like

    collectionView.reloadData()
    collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
    

    I don't know the specific use that you are wanting this for so I can't fully test how it should be but invalidateLayout seems like the wrong way to reload the collectionView.