使用自适应单元格的iOS 10中的collectionViewContentSize

10

iOS 10之前,我有一个自动调整大小的表视图,它仅由一个使用标准UICollectionViewFlowLayout的具有自适应大小单元格的UICollectionView组成。集合视图单元格使用自动布局进行调整大小。为了使表单元格正确调整大小,我不得不找到集合视图的内容大小,并在表单元格的systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:中使用该大小。

我还发现,如果没有调用collectionView layoutIfNeeded,collectionView.collectionViewLayout.collectionViewContentSize会使用estimatedItemSize而不是正确大小的单元格大小。这导致systemLayoutSizeFittingSize为:

- (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;
}

在 systemLayoutSizeFittingSize 方法中调用 layoutIfNeeded 导致了一个断言错误:*** Assertion failure in -[_UIFlowLayoutSection computeLayoutInRect:forSection:invalidating:invalidationContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3599.6/UIFlowLayoutSupport.m:823

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

4个回答

17

这是iOS10中仅限iPhone Plus设备的一些奇怪的bug。我也遇到了同样的问题,我的解决方法是像这样调用layoutIfNeeded

这是关于iOS10和iPhone Plus设备的一个奇怪的bug。我曾经遇到过同样的问题,我解决的方法是调用layoutIfNeeded函数,具体代码如下:

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

在不同的UICollectionViewDataSources方法中执行相同的操作也可以有效。


1
圣善啊,我本来会变成 head() -> Desk。我不想知道你是怎么发现的。 - Stan
1
我遇到的最奇怪的错误,导致了生产崩溃,简直是疯狂... - orxelm
@user924,就像我之前说的那样,“在不同的UICollectionViewDataSources方法中执行相同的操作也可以实现”,你可以试一下。 - orxelm

1
我在开发iOS 10应用时遇到了相同的问题。删除第一行代码解决了我的问题。 self.collectionView.frame = CGRectMake(0, 0, targetSize.width, FLT_MAX); //删除此行代码 希望这能帮到你!

如果不将框架设置为适当的宽度,则布局大小会被错误计算。虽然不会崩溃,但大小完全错误。最终,我用自定义网格UIView子类替换了我的集合视图,因为布局计算相对简单,而自动调整大小的集合视图则介于脆弱和无法使用之间。 - ManicJason
1
你尝试过调用 [self.collectionView.superView layoutIfNeeded]; 吗? - tuantm
这会导致集合视图中不同的断言失败。 - ManicJason

0

当我在iOS 10上开发我的应用程序并在awakeFromNib中将UICollectionViewDataSource设置为自身时,我遇到了相同的问题,就像这样:

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中,问题解决了,像这样:
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
}

希望这能帮到你!


0
在我的情况下,在布局之前调用invalidateLayout是解决此问题的一种方法。
UIViewController子类中:
override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    collectionView.collectionViewLayout.invalidateLayout()
}

或者在一个 UIView 子类中:

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

这会导致布局反馈循环。 - Harout360

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接