自调整集合视图在iOS 15中进入递归循环

vjhs03f7  于 2023-03-24  发布在  iOS
关注(0)|答案(4)|浏览(173)

我有一个自调整大小的集合视图,当我调用super.layoutSubviews时,由于集合视图进入递归更新循环,我的应用程序崩溃。这在iOS 14及以下版本中运行良好。但在iOS 15以后观察到它。

class DynamicCollectionView: UICollectionView {

override var contentSize: CGSize {
    didSet {
        invalidateIntrinsicContentSize()
    }
}

override func layoutSubviews() {
    super.layoutSubviews()
    if bounds.size != intrinsicContentSize {
        invalidateIntrinsicContentSize()
    }
}

override var intrinsicContentSize: CGSize {
    return contentSize
}

override func reloadData() {
    super.reloadData()
    invalidateIntrinsicContentSize()
    layoutIfNeeded()
}

}
Crash说:
由于未捕获异常“NSInternalInconsistencyException”,正在终止应用程序,原因:'UICollectionView(〈KPFlagship.SelfSizingCollectionView 0x 7 f896 b260 e00〉)在其更新/布局循环中卡住。发生这种情况的原因有很多,包括首选属性未返回一致大小的自调整大小视图。若要调试此问题,请检查Console应用程序中的“UICollectionViewRecursion”类别中的日志。'

bjp0bcyl

bjp0bcyl1#

在iOS15上手动计算单元格大小时面临相同的崩溃。
通过将IB中的collectionView设置为None来禁用Estimated Size,这对我来说是修复的。

j7dteeu8

j7dteeu82#

在我们的例子中(垂直流布局collectioview,垂直自调整大小的单元格),问题是我有一些单元格没有实现覆盖preferredLayoutAttributesFitting:

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    let targetSize = CGSize(width: layoutAttributes.frame.width, height: 0)
    layoutAttributes.frame.size = contentView
        .systemLayoutSizeFitting(targetSize,
                                 withHorizontalFittingPriority: .required,
                                 verticalFittingPriority: .fittingSizeLevel)
    return layoutAttributes
}

下面是与我们所拥有类似的flowlayout:

final class VerticalFlowLayout: UICollectionViewFlowLayout {
    
    override init() {
        super.init()
        scrollDirection = .vertical
        estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    }
        
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let layoutAttributesObjects = super.layoutAttributesForElements(in: rect)
        
        
        layoutAttributesObjects?.enumerated()
            .forEach { (index, layoutAttributes) in
                if layoutAttributes.representedElementCategory == .cell {
                    
                    guard let newFrame = layoutAttributesForItem(at: layoutAttributes.indexPath)?.frame else {
                        return
                    }
                    layoutAttributes.frame = newFrame
                }
            }
        
        return layoutAttributesObjects
    }
    
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        guard let collectionView = collectionView else {
            return nil
        }
        
        guard let layoutAttributes = super.layoutAttributesForItem(at: indexPath) else {
            return nil
        }
        
        layoutAttributes.frame.origin.x = sectionInset.left
        layoutAttributes.frame.size.width = collectionView.safeAreaLayoutGuide.layoutFrame.width - sectionInset.left - sectionInset.right
        
        return layoutAttributes
    }
}

所以,在iOS版本之前iOS 15collectionview和细胞没有问题.构建相同的代码后**iOS 15+**开始卡在其更新/布局循环.
因此,如果您遇到类似的问题,请尝试找出您正在使用的自定义布局类型,并尝试根据preferredLayoutAttributesFitting返回。

  • P.S.如果你(阅读的人)有任何见解,为什么它在ios 15之前工作而在ios 15之后不工作,ios 15实际上发生了什么变化导致了这样的问题,请与我们分享,ty:)*
ef1yzkbh

ef1yzkbh3#

我在iOS 15中遇到过类似的问题。通过覆盖UICollectionViewFlowLayout方法修复了它:

override func shouldInvalidateLayout(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, 
         withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> Bool {
    return true
}
wj8zmpe1

wj8zmpe14#

我也面临着同样的问题,因为在iOS 15之后,自调整单元格的大小也有问题。可以在苹果开发者论坛上找到讨论:https://developer.apple.com/forums/thread/694141 .
为了解决这个问题,我在IB尺寸检查器中将估计尺寸更改为无,如下图所示。

相关问题