2

According to multiple SO questions and answers, the right way of updating the layout of UICollectionView is to call invaliditateLayout() from within the UICollectionViewController's viewDidLayoutSubviews(). In my case, however, this causes an infinite loop, because after invalidating the layout, viewDidLayoutSubviews() gets called again etc.

Is it an artifact of some error I made somewhere, and so do I need to fix it? What could be the cause? Or is there any other new recommended way on how to invalidate layout?

Per request, here is the SO thread/answer I was referring to.

Per another request, the relevant piece of code follows. I set the size of the collection view with autolayout, and want to show exactly one item at once in the collection view, so I need to dynamically set its size after autolayout finishes. I do that using flow layout delegate.

// In ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

// necessary to prevent loop
var shouldLayout = true 
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    guard let collectionView = collectionView else { return }

    if shouldLayout {
        collectionView.collectionViewLayout.invalidateLayout()
        shouldLayout = false
    }
}

// Later in the file
func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {

    // Height and width to fit exactly one item into the CollectionView...
}
Eugleo
  • 348
  • 1
  • 10
  • 3
    Why do you need to invalidate the layout ? What I don't understand is why you want to "relayout" your view just after it finishes to "layout". – Xavier Bauquet Feb 26 '18 at 08:17
  • Do you use `UICollectionViewController`? – kelin Feb 26 '18 at 08:28
  • @sh4rp-eye : Just curious, can you post any links to accepted answer on SO that says call `invaliditateLayout` in `viewDidLayoutSubviews` because this will anyway lead to loop wonder how can that be solution in any case ! – Sandeep Bhandari Feb 26 '18 at 08:50
  • 1
    can you include links to the questions and answers that suggest to use `invalidateLayout` in `viewDidLayoutSubviews`? – Milan Nosáľ Feb 26 '18 at 08:50
  • @SandeepBhandari the OP might be talking about [this answer](https://stackoverflow.com/a/36884467/3687801) – nayem Feb 26 '18 at 10:01
  • 1
    @nayem : In a link you posted you are invalidating the collectionView layout in ViewDidLayout of ViewController. In OP's case he is invalidating the layout in its own ViewDidLayoutSubViews :) They aren't same – Sandeep Bhandari Feb 26 '18 at 10:03
  • 1
    Well @SandeepBhandari, nice catch. Then he might be confused with the same method signature without noticing the presence of `ViewController`'s overridden method. Even actually I too didn't notice that prior to your comment – nayem Feb 26 '18 at 10:07
  • @XavierBauquet My CollectionView is in a StackView, and I'd like to have exactly one item per page. So, I invalidate the layout after the autolayout finishes and implement a sizeForItemAt method, which uses collectionView.frame.Width. Is there a better way? – Eugleo Feb 26 '18 at 10:09
  • @SandeepBhandari I don't understand. I am overriding the UIViewController method, too. – Eugleo Feb 26 '18 at 10:18
  • @sh4rp-eye : Please post the viewDidLayoutSubviews method to let us understand your problem better – Sandeep Bhandari Feb 26 '18 at 10:27
  • @SandeepBhandari Done, please see the updated post. – Eugleo Feb 26 '18 at 11:10

0 Answers0