UICollectionView - iOS 10 - crash on iPhone 6 Plus

2019-03-15 05:50发布

问题:

I've created an UICollectionView that works fine on small devices like iPhone 5s/SE/6/6s/7 on both simulator and real device, but I have a strange situation when it comes about iPhone 6Plus, iPhone 7Plus and any iPad version. It works fine on real device, but it crashes in simulator with the following error:

Assertion failure in -[_UIFlowLayoutSection computeLayoutInRect:forSection:invalidating:invalidationContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.5.2/UIFlowLayoutSupport.m:823

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionViewFlowLayout internal error'

What I found out so far is that if I remove the estimatedItemSize it works fine but the auto-layout doesn't anymore, but if I have that enabled it crashes in simulator.

I am using the latest Xcode version and iOS 10.

Any ideas why it's crashing?

回答1:

Calling invalidateLayout before layout is a workaround for this issue.

In a UIViewController subclass:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    collectionView.collectionViewLayout.invalidateLayout()
}

or in a UIView subclass:

override func layoutSubviews() {
    super.layoutSubviews()
    collectionView.collectionViewLayout.invalidateLayout()
}


回答2:

This is some strange bug in iOS10 with iPhone Plus devices only. I've faced the same issue, my solution was to call layoutIfNeeded like this:

func numberOfSections(in collectionView: UICollectionView) -> Int {
    collectionView.layoutIfNeeded() // Patch: only to solve UIKit crash on Plus models
    return 1
}

Doing the same thing in different UICollectionViewDataSources methods will work as well

Answer that worked for me based on orxelm's answer on collectionViewContentSize in iOS 10 using self-sizing cells

Invalidating the layout seemed to prevent my collectionView from using my flow layout, and instead used the default layout. This forced all my cells to be the same size which was not the desired outcome (for me anyway).