在iOS 10中使用自调整单元格的collectionViewContentSize

在iOS 10中使用自调整单元格的collectionViewContentSize,ios,objective-c,uicollectionview,ios10,Ios,Objective C,Uicollectionview,Ios10,在iOS 10之前,我有一个自调整大小的表视图,它仅由一个UICollectionView组成,带有使用标准UICollectionViewFlowLayout自调整大小的单元格。使用“自动布局”调整集合视图单元格的大小。为了使表格单元格能够正确调整自身大小,我必须找到集合视图的内容大小,并在表格单元格的systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:中使用它 我还发现对colle

在iOS 10之前,我有一个自调整大小的表视图,它仅由一个UICollectionView组成,带有使用标准UICollectionViewFlowLayout自调整大小的单元格。使用“自动布局”调整集合视图单元格的大小。为了使表格单元格能够正确调整自身大小,我必须找到集合视图的内容大小,并在表格单元格的systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:中使用它

我还发现对collectionView.collectionViewLayout.collectionViewContentSize的调用使用了estimatedItemSize而不是正确大小的单元格大小,除非我调用collectionView LayoutFneed。这导致SystemLayoutSizeSettings大小为:

- (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;
}
现在调用LayoutFineded会导致-[\u UIFlowLayoutSection ComputeLayoutRect:forSection:invalidating:invalidationContext:],/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit\u Sim/UIKit-3599.6/UIFlowLayoutSupport.m:823中的断言失败


我在systemLayoutSizeFittingSize中调用LayoutFeeded是否违反了一些道德规则?在使用自调整单元格时,是否有更好的方法来计算集合视图的内容大小?我不想从自动布局转移到用代码计算尺寸,但这肯定是最糟糕的选择。

在iOS 10上开发应用程序时,我也遇到了同样的问题。删除第一行解决了我的问题

self.collectionView.frame=CGRectMake(0,0,targetSize.width,FLT_MAX)//去掉这个


希望这有帮助

这是iOS10中一些奇怪的错误,仅适用于iPhone Plus设备。我也遇到过同样的问题,我的解决方案是这样调用
layoutifneed

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

在不同的UICollectionViewDataSources方法中执行相同的操作同样有效

在我的例子中,在布局之前调用
invalidateLayout
是解决此问题的一种解决方法

UIViewController
子类中:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    collectionView.collectionViewLayout.invalidateLayout()
}
override func layoutSubviews() {
    super.layoutSubviews()
    collectionView.collectionViewLayout.invalidateLayout()
}
或者在
ui视图
子类中:

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

我在iOS 10上开发应用程序时遇到了同样的问题,并在
awakeFromNib
上将
UICollectionViewDataSource
设置为自身,如下所示:

func numberOfSections(in collectionView: UICollectionView) -> Int {
    collectionView.layoutIfNeeded() // Patch: only to solve UIKit crash on Plus models
    return 1
}
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
}
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
}
然后我将
UICollectionViewDataSource
设置代码移动到
layoutSubviews
,问题得到解决,如下所示:

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

希望这有帮助

如果未将框架设置为适当的宽度,则布局大小计算错误。它没有崩溃,但是尺寸完全错了。我最终用一个自定义网格UIView子类替换了我的集合视图,因为布局计算相对简单,并且自调整集合视图的大小介于脆弱和不可用之间。您是否尝试调用
[self.collectionView.superView layoutifneed]在集合视图中导致另一个断言失败。天哪,我本来应该是
head()->Desk
。我不想知道你是怎么发现这个的。这是我遇到过的最奇怪的错误,我的生产崩溃得像疯了一样…@user924,正如我说的“在不同的UICollectionViewDataSources方法中做同样的事情也可以”试试。这会导致布局反馈循环