【问题标题】:'UICollectionView must be initialized with a non-nil layout parameter'?'UICollectionView 必须使用非零布局参数初始化'?
【发布时间】:2019-09-16 10:45:43
【问题描述】:

我正在尝试编写一个自定义类来创建一个 UICollectionView,我打算从不同的类中创建多个实例。下面是我在自定义 UICollectionView 类中使用的代码:

import UIKit

class CustomCollectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource {



    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {

        super.init(frame: frame, collectionViewLayout: layout)

        setupCollectionView(topEdgeInset: 20, bottomEdgeInset: 20, leftEdgeInset: 20, rightEdgeInset: 20, screenWdith: frame.width, screenHeight: frame.height, minimumCellsHorizontalSpacing: 20, minimumCellsVerticalSpacing: 20, numberOfCellsPerRow: 2, viewCollectionViewWillBeAddedTo: self, dataSource: self as! UICollectionViewDataSource, delegate: self as! UICollectionViewDelegate)

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    convenience init(topEdgeInset: CGFloat, bottomEdgeInset: CGFloat, leftEdgeInset: CGFloat, rightEdgeInset: CGFloat, screenWdith: CGFloat, screenHeight: CGFloat, minimumCellsHorizontalSpacing: CGFloat, minimumCellsVerticalSpacing: CGFloat, numberOfCellsPerRow: CGFloat, viewCollectionViewWillBeAddedTo: UIView, dataSource: UICollectionViewDataSource, delegate: UICollectionViewDelegate) {

        self.init(frame: viewCollectionViewWillBeAddedTo.bounds,collectionViewLayout: UICollectionViewFlowLayout())

        setupCollectionView(topEdgeInset: topEdgeInset, bottomEdgeInset: bottomEdgeInset, leftEdgeInset: leftEdgeInset, rightEdgeInset: rightEdgeInset, screenWdith: screenWdith, screenHeight: screenHeight, minimumCellsHorizontalSpacing: minimumCellsHorizontalSpacing, minimumCellsVerticalSpacing: minimumCellsVerticalSpacing, numberOfCellsPerRow: numberOfCellsPerRow, viewCollectionViewWillBeAddedTo: viewCollectionViewWillBeAddedTo, dataSource: dataSource, delegate: delegate)

    }

    func setupCollectionView (topEdgeInset topInset: CGFloat, bottomEdgeInset bottomInset: CGFloat, leftEdgeInset leftInset: CGFloat, rightEdgeInset rightInset: CGFloat, screenWdith width: CGFloat, screenHeight height: CGFloat, minimumCellsHorizontalSpacing cellsHorizontalSpacing: CGFloat, minimumCellsVerticalSpacing cellsVerticalSpacing: CGFloat, numberOfCellsPerRow cellsPerRow: CGFloat, viewCollectionViewWillBeAddedTo hostView: UIView, dataSource: UICollectionViewDataSource, delegate: UICollectionViewDelegate) {

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()

        layout.sectionInset = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)

        layout.minimumLineSpacing = cellsVerticalSpacing

        layout.minimumInteritemSpacing = cellsHorizontalSpacing

        let widthOfCollectionViewCell: CGFloat = width - (leftInset + rightInset + cellsHorizontalSpacing) / cellsPerRow

        layout.itemSize = CGSize(width: widthOfCollectionViewCell, height: 100)

        let myCollectionView = UICollectionView(frame: hostView.bounds, collectionViewLayout: layout)

        myCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")

        myCollectionView.dataSource = dataSource

        myCollectionView.delegate = delegate

        hostView.addSubview(self)

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 8
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)

        myCell.backgroundColor = .blue

        return myCell
    }

}

下面的类是我从上面的自定义 UICollectionView 类创建一个实例的地方:

class FirstItemInTabBarOpenRolledSections: UIViewController
{

    override func viewDidLoad() {

        super.viewDidLoad()

        view.backgroundColor = .black

    }

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)
_ = CustomCollectionView(topEdgeInset: 20, bottomEdgeInset: 20, leftEdgeInset: 20, rightEdgeInset: 20, screenWdith: self.view.frame.width, screenHeight: self.view.frame.height, minimumCellsHorizontalSpacing: 20, minimumCellsVerticalSpacing: 20, numberOfCellsPerRow: 2, viewCollectionViewWillBeAddedTo: self.view, dataSource: self as! UICollectionViewDataSource, delegate: self as! UICollectionViewDelegate)

    }
func numberOfSections(in collectionView: UICollectionView) -> Int {

        return 1

    }


    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        print("User tapped on itme \(indexPath.row)")

    }

}

但是,每次我运行应用程序时,它都会崩溃并且我收到一条错误消息:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“UICollectionView 必须使用非零布局参数初始化”

我不明白我的布局没有初始化??谁能指出问题出在哪里?

【问题讨论】:

  • 我回滚了您上次的大编辑,因为发布工作代码代替原始代码会使整个问题变得不必要,并且不需要任何答案。如果有的话,请使用您的工作代码发布您自己的答案。

标签: swift layout uicollectionview


【解决方案1】:

错误很明显。您需要在创建集合视图时指定布局,但您不这样做。

为方便起见init,您可以拨打self.init(),但您必须拨打self.init(frame:,collectionViewLayout:)

您需要重构您的 setupCollectionView 方法,作为正确处理的一部分。

【讨论】:

  • 感谢您的快速回复。按照您的回答,我修改了自定义 UICollectionView 中的代码以及 ViewController 中的代码,其中我从自定义 UICollectionView 类创建了第一个实例,如上所示。但是,现在我收到此错误“无法将 'EC3_Cross_Section_Classification.FirstItemInTabBarOpenRolledSections' (0x106f924d8) 类型的值转换为 'UICollectionViewDataSource' (0x1128dfb70)。”
  • 这是一个全新的问题。
  • 谢谢,我完全理解你的意思。我设法解决了这个问题,但是,并不完全符合我的要求,请查看上面更新的代码,了解我是如何解决这个问题的。在一个理想的世界中,我想让自定义 UICollectionView 类处理与我想稍后在其他 ViewControllers 中创建多个实例的 CollectionView 相关的所有内容。甚至诸如:
  • myCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell") myCollectionView.dataSource = self myCollectionView.delegate = self myCollectionView.backgroundColor = .white self.view.addSubview(myCollectionView)
  • 目前正在UIViewController类中处理。
猜你喜欢
  • 2014-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-09
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 2017-04-08
相关资源
最近更新 更多