使用多个UICollectionView,出现错误,“…必须用非零布局进行初始化”

我最近开始使用Swift,我试图从页面上的一个UICollectionView(工作)到其中的两个。 我收到错误

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

到目前为止,我发现堆栈溢出已经被合并到我的代码中,但我仍然收到错误。 我在智慧的结尾,请帮助!

我去过的地方:

  • 我开始设置UICollectionView 这篇文章 ,一切工作得很好。
  • 现在在同一个屏幕上设置第二个UICollectionView,我按照本文中的说明操作。
  • 一切似乎没问题,我得到“build设成功”,随着应用程序开始运行,迅速崩溃。 错误信息说:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'

  • 在StackOverflow中寻找这个错误,我发现这篇文章 (处理单个UICollectionView,而不是我有两个)。
  • 我已经从那篇文章中实现了我所能做到的一切,但是我仍然遇到了这个错误,现在已经没有想法了。 我的代码如下,任何帮助将非常感激!

ViewController.swift

 import UIKit class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { var collectionViewLeft = UICollectionView() // changed "let" to "var" so I can assign things to it in viewDidLoad() var collectionViewRight = UICollectionView() let collectionViewLeftIdentifier = "CollectionViewLeftCell" let collectionViewRightIdentifier = "CollectionViewRightCell" override func viewDidLoad() { super.viewDidLoad() let layoutLeft = UICollectionViewFlowLayout() // this is what **I would think** would be my non-nil layout layoutLeft.itemSize = CGSize(width: 100, height: 100) let layoutRight = UICollectionViewFlowLayout() layoutRight.itemSize = CGSize(width: 100, height: 100) collectionViewLeft = UICollectionView(frame: self.view.frame, collectionViewLayout: layoutLeft) collectionViewRight = UICollectionView(frame: self.view.frame, collectionViewLayout: layoutRight) collectionViewLeft.delegate = self collectionViewRight.delegate = self collectionViewLeft.dataSource = self collectionViewRight.dataSource = self self.view.addSubview(collectionViewLeft) self.view.addSubview(collectionViewRight) collectionViewLeft.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier) collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier) } let reuseIdentifierLeft = "cellLeft" // also enter this string as the cell identifier in the storyboard let reuseIdentifierRight = "cellRight" var itemsRight = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"] var itemsLeft = ["10", "20", "30", "40", "50", "60"] // MARK: - UICollectionViewDataSource protocol // tell the collection view how many cells to make func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if collectionView == self.collectionViewLeft { return self.itemsLeft.count } else if collectionView == self.collectionViewRight { return self.itemsRight.count } else { print("This is very bad") assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!") return 0 } } // make a cell for each cell index path func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if collectionView == self.collectionViewLeft { // get a reference to our storyboard cell let cellLeft = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierLeft, for: indexPath as IndexPath) as! MyCollectionViewCell // Use the outlet in our custom class to get a reference to the UILabel in the cell cellLeft.myLeftLabel.text = self.itemsLeft[indexPath.item] cellLeft.backgroundColor = UIColor.red // make cell more visible in our example project return cellLeft } else if collectionView == self.collectionViewRight { let cellRight = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierRight, for: indexPath as IndexPath) as! MyRightCollectionViewCell // Use the outlet in our custom class to get a reference to the UILabel in the cell cellRight.myRightLabel.text = self.itemsRight[indexPath.item] cellRight.backgroundColor = UIColor.green // make cell more visible in our example project return cellRight } else { print("This is very bad") assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!") // won't actually execute the following, but to keep the compiler happy... let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierLeft, for: indexPath as IndexPath) as! MyCollectionViewCell return cell } } // MARK: - UICollectionViewDelegate protocol func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { // handle tap events if collectionView == self.collectionViewLeft { print("You tapped cell #\(indexPath.item) on the LEFT!") } else if collectionView == self.collectionViewRight { print("You tapped cell #\(indexPath.item) on the RIGHT!") } else { print("This is very bad") assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!") } } 

}

MyCollectionViewCell.swift

 import UIKit class MyCollectionViewCell: UICollectionViewCell { @IBOutlet weak var myLeftLabel: UILabel! } class MyRightCollectionViewCell: UICollectionViewCell { @IBOutlet weak var myRightLabel: UILabel! } 

我的猜测,你声明UICollectionViewController的空默认的init构造函数作为variables:

 var collectionViewLeft = UICollectionView() var collectionViewRight = UICollectionView() 

尝试replace你的variables声明没有构造函数:

下面的编辑代码:正如@ Paulw11在下面的答案中正确指出的那样,最好使用隐式解包的可选项! 而不是 ?

 var collectionViewLeft: UICollectionView! var collectionViewRight: UICollectionView! 

无论如何,你正在使用指定的UICollectionView初始化函数在你的viewDidLoad函数中实例化它们。

注意,最好在将UICollectionView作为子视图添加之前注册自定义类/ xib。 现在并不重要,但在重构之后可能会出现问题,因为在为单元注册自定义类代码之前,您的代码可以调用UICollectionView delegatedataSource函数。 只需将您的代码调用到.register()之上的.register() self.view.addSubview()

 collectionViewLeft.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier) collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier) 

不要将空的UICollectionView对象分配给你的属性; 你只是要把它们扔掉,这是因为你没有提供布局而导致exception。 在这种情况下,您可以使用隐式解包的可选项:

 var collectionViewLeft: UICollectionView! var collectionViewRight: UICollectionView!