简体   繁体   English

使用多个UICollectionView时,出现错误,“ ...必须使用非nil布局初始化”

[英]With Multiple UICollectionView's, getting error, “… must be initialized with non-nil layout”

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. 我最近开始使用Swift,并且正在尝试从页面上的一个UICollectionView(有效)到其中的两个。 I am getting the error 我收到错误

"Terminating app due to uncaught exception ' NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter '". “由于未捕获的异常' NSInvalidArgumentException'而终止应用程序,原因:'UICollectionView必须使用非空布局参数 ' 初始化 。”

What I've found thus far on Stack Overflow has been incorporated into my code, but I am still getting the error. 到目前为止,我在Stack Overflow上发现的内容已合并到我的代码中,但是仍然出现错误。 I am at my wit's end, please help! 我机智到极了,请帮忙!

Where I've been: 我去过的地方:

  • I Started with this article on setting up the UICollectionView, and everything worked just fine. 我从这篇关于设置UICollectionView的文章开始,一切都很好。
  • Now to set up a second UICollectionView on the same screen, I followed the instructions in this article . 现在,在同一屏幕上设置第二个UICollectionView,我按照本文中的说明进行操作。
  • Everything seems okay, I get "Build Succeeded", followed promptly by a crash as the app starts to run. 一切似乎都还好,我得到“ Build Succeeded”,然后在应用开始运行时立即崩溃。 Error message says: 错误消息说:

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

  • Looking for that error in StackOverflow, I find this article (which deals with a single UICollectionView, rather than the two that I have). 在StackOverflow中寻找该错误时,我找到了这篇文章该文章涉及一个UICollectionView,而不是我的两个UICollectionView)。
  • 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 : 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 MyCollectionViewCell.swift

import UIKit

class MyCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var myLeftLabel: UILabel!

}

class MyRightCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var myRightLabel: UILabel!

}

Don't assign empty UICollectionView objects to your properties; 不要将空的UICollectionView对象分配给您的属性; you are just going to throw them away anyway and it is causing the exception since you aren't providing a layout. 您将无论如何都将它们扔掉,并且由于未提供布局而导致了异常。 This is a situation where you can use an implicitly unwrapped optional: 在这种情况下,您可以使用隐式展开的可选:

var collectionViewLeft: UICollectionView!                        
var collectionViewRight: UICollectionView!

My guess, you declare UICollectionViewController 's with empty default init constructor as variables: 我的猜测是,您将具有空默认init构造函数的UICollectionViewController声明为变量:

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

Try to replace your variable declarations without constructors: 尝试替换不带构造函数的变量声明:

Edited code below: As @Paulw11 correctly noted in his answer below, it's better to use an implicitly unwrapped optional ! 下面的编辑代码:正如@ Paulw11在下面的答案中正确指出的那样,最好使用隐式解包的可选内容! rather than ? 而不是 ?

var collectionViewLeft: UICollectionView!
var collectionViewRight: UICollectionView!

Anyway, you are instantiate them in your viewDidLoad function with designated initialisers for UICollectionView . 无论如何,您可以使用指定的UICollectionView初始化程序在viewDidLoad函数中实例化它们。

And just a note, it's better to register custom class / xibs before UICollectionView is added as a subview. 请注意,最好在将UICollectionView添加为子视图之前注册自定义类/ xibs。 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. 现在不是很关键,但是在重构等之后可能会成为问题,因为在编写单元格的注册自定义类之前,您可以在代码中调用UICollectionView delegatedataSource函数。 Just move your code with calls to .register() above self.view.addSubview() : 只是通话将您的代码.register()以上self.view.addSubview()

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 错误:UICollectionView必须使用非nil布局参数初始化 - Error: UICollectionView must be initialized with a non-nil layout parameter 'UICollectionView必须使用非nil布局参数初始化'-Swift 4 - 'UICollectionView must be initialized with a non-nil layout parameter' - Swift 4 “ UICollectionView必须使用非null布局参数初始化” - 'UICollectionView must be initialized with a non-nil layout parameter' UICollectionView:必须使用非 nil 布局参数初始化 - UICollectionView: must be initialized with a non-nil layout parameter UiCollectionView必须使用非nil布局参数初始化Swift 3 - UiCollectionView must be initialized with a non-nil layout parameter Swift 3 必须使用非nil布局参数初始化UICollectionView。 迅速与UICollectionView错误 - UICollectionView must be initialized with a non-nil layout parameter. error in swift with UICollectionView 即使在UICollectionView文件中定义了参数,也必须在Swift中使用非nil布局参数初始化UICollectionView - UICollectionView must be initialized with a non-nil layout parameter in Swift, even though the parameter is defined in the UICollectionView file 由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'UICollectionView必须使用非nil布局参数初始化 - Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter 使用JSQMessagesCollectionView时,“ UICollectionView必须使用非nil布局参数初始化” - 'UICollectionView must be initialized with a non-nil layout parameter' while using JSQMessagesCollectionView Swift 3.0 中的 UICollectionViewController 错误:必须使用非 nil 布局参数进行初始化 - UICollectionViewController Error in Swift 3.0: must be initialized with a non-nil layout parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM