the behavior of the UICollectionViewFlowLayout is not defined, because the cell width is greater than collectionView width

后端 未结 20 2157
温柔的废话
温柔的废话 2020-12-01 01:53

2015-08-18 16:07:51.523 Example[16070:269647] the behavior of the UICollectionViewFlowLayout is not defined because: 2015-08-18 16:07:51.523
Example

相关标签:
20条回答
  • 2020-12-01 02:22

    I've also seen this occur when we set the estimatedItemSize to automaticSize and the computed size of the cells is less than 50x50 (Note: This answer was valid at the time of iOS 12. Maybe later versions have it fixed).

    i.e. if you are declaring support for self-sizing cells by setting the estimated item size to the automaticSize constant:

    flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    

    and your cells are actually smaller than 50x50 points, then UIKit prints out these warnings. FWIW, the cells are eventually sized appropriately and the warnings seem to be harmless.

    One fix workaround is to replace the constant with a 1x1 estimated item size:

    flowLayout.estimatedItemSize = CGSize(width: 1, height: 1)
    

    This does not impact the self-sizing support, because as the documentation for estimatedItemSize mentions:

    Setting it to any other value causes the collection view to query each cell for its actual size using the cell’s preferredLayoutAttributesFitting(_:) method.

    However, it might/might-not have performance implications.

    0 讨论(0)
  • 2020-12-01 02:22

    This solution definitely works.. Try this code

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
    
    {
    
     collectionView.collectionViewLayout.invalidateLayout()
    
     super.viewWillTransition(to: size, with: coordinator)
    
    }
    
    0 讨论(0)
  • 2020-12-01 02:26

    Any Changes in UIView must be done from main thread. Put your code of collectionView addition to views hierarchy into:

    DispatchQueue.main.async {
        ...  
    }
    
    0 讨论(0)
  • 2020-12-01 02:26

    I've been struggling with this problem for some hours, too.

    My UICollectionViewController is embedded in a container view, when rotating the iPad from landscape to portrait it showed the error. The cells did resize though.

    I solved the error by calling the following in the UICollectionViewController:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        self.collectionView.collectionViewLayout.invalidateLayout()
    
        super.viewWillTransition(to: size, with: coordinator)
    }
    

    The "super" has to be called after invalidating the layout.

    Additionally I needed to call the following in the view where the container view is embedded in:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
    
        DispatchQueue.main.async {
            self.collectionViewController.collectionView.reloadData()
        }
    }
    

    This way, the cells are updated after the screen rotation is done.

    0 讨论(0)
  • 2020-12-01 02:31

    select collectionview in storyboard go to size inspector change estimate size to none

    0 讨论(0)
  • 2020-12-01 02:32

    After doing some experimenting, this seems to also be tied to how you layout your collectionView.

    The tl;dr is: Use AutoLayout, not autoresizingMask.

    So for the core of the problem the best solutions I've found to handle orientation change use the following code, which all makes sense:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
    
        coordinator.animate(alongsideTransition: { (context) in
            self.collectionView.collectionViewLayout.invalidateLayout()
        }, completion: nil)
    }
    

    However, there are still situations where you can get the item size warning. For me it's if I am in landscape in one tab, switch to another tab, rotate to portrait, then return to the previous tab. I tried invalidating layout in willAppear, willLayout, all the usual suspects, but no luck. In fact, even if you call invalidateLayout before super.willAppear() you still get the warning.

    And ultimately, this problem is tied to the size of the collectionView bounds updating before the delegate is asked for the itemSize.

    So with that in mind I tried using AutoLayout instead of collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight], and with that, problem solved! (I use SnapKit to do AutoLayout so that I don't pull my hair out constantly). You also just need to invalidateLayout in viewWillTransition (without the coordinator.animate, so just as you have in your example), and also invalidateLayout at the bottom of viewWillAppear(:). That seems to cover all situations.

    I dont know if you are using autoresizing or not - it would be interesting to know if my theory/solution works for everyone.

    0 讨论(0)
提交回复
热议问题