collectionViewContentSize in iOS 10 using self-siz

2019-03-26 11:20发布

问题:

Prior to iOS 10, I had a self-sizing table view that solely consisted of a UICollectionView with self-sizing cells using a standard UICollectionViewFlowLayout. The collection view cells are sized using auto-layout. In order for the table cell to size itself correctly, I had to find the collection view's content size and use that within the table cell's systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:.

I also found that the call to collectionView.collectionViewLayout.collectionViewContentSize used the estimatedItemSize instead of the correctly sized cell sizes unless I called collectionView layoutIfNeeded. This resulted in a systemLayoutSizeFittingSize of:

- (CGSize) systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority
{
    self.collectionView.frame = CGRectMake(0, 0, targetSize.width, FLT_MAX);
    [self.collectionView layoutIfNeeded];

    CGSize collectionViewContentSize = self.collectionView.collectionViewLayout.collectionViewContentSize;
    CGFloat verticalPadding = fabs(self.collectionViewTopPaddingConstraint.constant) + fabs(self.collectionViewBottomPaddingConstraint.constant);
    CGSize cellSize = CGSizeMake(collectionViewContentSize.width, collectionViewContentSize.height + verticalPadding);

    return cellSize;
}

The call to layoutIfNeeded now causes a *** Assertion failure in -[_UIFlowLayoutSection computeLayoutInRect:forSection:invalidating:invalidationContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3599.6/UIFlowLayoutSupport.m:823

Am I violating some ethical rule by calling layoutIfNeeded within systemLayoutSizeFittingSize? Is there some better method to calculate a collection view's content size when it is using self-sizing cells? I would rather not have to move from auto layout to doing these size calculations in code, but that is certainly a worst case option.

回答1:

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



回答2:

I got same issue when develop my app on iOS 10. Remove the first line solved my problem.

self.collectionView.frame = CGRectMake(0, 0, targetSize.width, FLT_MAX); //Remove this

Hope this help!



回答3:

In my case, 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()
}


回答4:

I got same issue when develop my app on iOS 10 and set UICollectionViewDataSource to itself on awakeFromNib,like this:

override func awakeFromNib() {
    super.awakeFromNib()
    let layout = UICollectionViewFlowLayout()
    // set your layout 
    collectionViewLayout = layout
    // set dataSource equal to self in here cause a crash
    dataSource = self
}

then I move the UICollectionViewDataSource setting code to layoutSubviews,the problem solved,like this:

override func layoutSubviews() {
        super.layoutSubviews()
        dataSource = self
    }

override func awakeFromNib() {
    super.awakeFromNib()
    let layout = UICollectionViewFlowLayout()
    // set your layout 
    collectionViewLayout = layout
    // set dataSource equal to self in here cause a crash
    dataSource = self
}

Hope this help!