layoutAttributesForElements 上的自定大小左对齐 CollectionView 崩溃

Posted

技术标签:

【中文标题】layoutAttributesForElements 上的自定大小左对齐 CollectionView 崩溃【英文标题】:Self-sizing Left Aligned CollectionView Crash on layoutAttributesForElements 【发布时间】:2019-10-08 02:41:31 【问题描述】:

我想做一个左对齐的自调整collectionView,就像这样:

这是我的示例项目: https://github.com/DiaobaoMiaoo/LeftAlignedSelfSizingCollectionView

运行项目后,将设备从纵向旋转到横向,然后按下红色按钮。然后应用程序似乎会从layoutAttributesForElements 崩溃并带有日志:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack: 

知道是什么原因以及如何解决此问题吗?谢谢!

我还尝试了我在网上找到的其他方法来实现左对齐的 CollectionView,包括:

Left Align Cells in UICollectionView

https://github.com/mokagio/UICollectionViewLeftAlignedLayout

https://github.com/mischa-hildebrand/AlignedCollectionViewFlowLayout

但它们都有一个相同的问题,如果单元格的内容比 collectionView.framce.width 长得多,那么应用程序将在 ios11 上的控制台中冻结。

【问题讨论】:

请检查答案,崩溃已解决。 【参考方案1】:

问题在于您的芯片单元中的布局约束。我建议您实现一种干净的方式,以便您可以跟踪何时创建、存储和清除布局约束,因为单元格布局依赖于父级。但就目前而言,希望这能解决您的崩溃问题并带您实现目标。

class ChipCell: UICollectionViewCell 

    var text: String? 
        didSet 
            label.text = text
        
    

    override init(frame: CGRect) 
        super.init(frame: frame)

        backgroundColor = .lightGray
        layer.cornerRadius = 2.0
        layer.masksToBounds = true

        addSubview(label)
        label.topAnchor.constraint(equalTo: topAnchor, constant: 2.0).isActive = true
        label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 2.0).isActive = true
        // label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0).isActive = true
        // label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0.0).isActive = true

    

    @available(*, unavailable)
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    override open var intrinsicContentSize: CGSize 
        return CGSize(width: label.intrinsicContentSize.width + 4,
                      height: label.intrinsicContentSize.height + 4)
    

    private let label: UILabel = 
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textAlignment = .center
        label.textColor = .black
        return label
    ()

【讨论】:

请检查上面的答案问题是在旋转collectionView上没有调用无效方法。【参考方案2】:

在 ViewController 中添加以下方法,它将正常工作而不会崩溃。

override func viewWillLayoutSubviews() 
        super.viewWillLayoutSubviews()
        container.viewModel = viewModel
    

崩溃的原因是在旋转您的 collectionView 布局时未因崩溃而失效。

【讨论】:

以上是关于layoutAttributesForElements 上的自定大小左对齐 CollectionView 崩溃的主要内容,如果未能解决你的问题,请参考以下文章