使用多个UICollectionView,获取错误,“...必须使用非零布局初始化”。 [英] With Multiple UICollectionView's, getting error, "... must be initialized with non-nil layout"
问题描述
我最近开始使用Swift,我试图从页面上的一个UICollectionView(有效)到最多两个。我收到错误
I have recently started working with Swift, and I am trying to go from one UICollectionView on the page (which worked) up to two of them. I am getting the error
因未捕获的异常而终止应用程序' NSInvalidArgumentException',原因:'UICollectionView必须初始化为非零布局参数'。
到目前为止我在Stack Overflow上找到的内容已经整合到我的代码中,但我仍然收到错误。我在我的智慧结束,请帮助!
What I've found thus far on Stack Overflow has been incorporated into my code, but I am still getting the error. I am at my wit's end, please help!
我去过的地方:
- 我开始使用这篇文章关于设置UICollectionView,一切正常。
- 现在在同一个屏幕上设置第二个UICollectionView,我按照这篇文章。
- 一切似乎都没问题,我得到Build Succeeded,紧随其后应用程序开始运行时,崩溃迅速发生。错误消息显示:
- I Started with this article on setting up the UICollectionView, and everything worked just fine.
- Now to set up a second UICollectionView on the same screen, I followed the instructions in this article.
- Everything seems okay, I get "Build Succeeded", followed promptly by a crash as the app starts to run. Error message says:
***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'UICollectionView必须使用非零布局参数初始化'
- 在StackOverflow中查找该错误,我找到< a href =https://stackoverflow.com/questions/40417252/uicollectionviewcontroller-error-in-swift-3-0-must-be-initialized-with-a-non-ni>这篇文章(它处理的是单个UICollectionView,而不是我所拥有的两个。
- 我已经从那篇文章中实现了所有内容,但我仍然收到错误,现在我出于想法。我的代码如下,任何帮助都将非常感谢!
- Looking for that error in StackOverflow, I find this article (which deals with a single UICollectionView, rather than the two that I have).
- I've implemented everything I can from that article, but I'm still getting the error, and am now out of ideas. My code is below, any help would be most greatly appreciated!
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
构造函数作为变量:
My guess, you declare UICollectionViewController
's with empty default init
constructor as variables:
var collectionViewLeft = UICollectionView()
var collectionViewRight = UICollectionView()
尝试在没有构造函数的情况下替换变量声明:
Try to replace your variable declarations without constructors:
以下编辑的代码:正如@ Paulw11正确指出的那样他的回答如下,最好使用一个隐式解包的可选项!而不是?
Edited code below: As @Paulw11 correctly noted in his answer below, it's better to use an implicitly unwrapped optional ! rather than ?
var collectionViewLeft: UICollectionView!
var collectionViewRight: UICollectionView!
无论如何,你要在 viewDidLoad
具有指定初始化程序的功能 UICollectionView
。
Anyway, you are instantiate them in your viewDidLoad
function with designated initialisers for UICollectionView
.
只需注意,最好先注册自定义类/ xib UICollectionView
被添加为子视图。它现在并不重要,但在重构后可能会出现问题。等,因为您的代码可以调用 UICollectionView
委托
或 dataSource
在为单元格编写注册的自定义类之前的函数。只需调用 .register()
上面的 self.view.addSubview()
:
And just a note, it's better to register custom class / xibs before UICollectionView
is added as a subview. It's not critical right now, but may be a problem after refactoring & etc., because you code can call UICollectionView
delegate
or dataSource
functions before you code registered custom classes for cells. Just move your code with calls to .register()
above self.view.addSubview()
:
collectionViewLeft.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier)
collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier)
这篇关于使用多个UICollectionView,获取错误,“...必须使用非零布局初始化”。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!