使用多个UICollectionView,获取错误,“...必须使用非零布局初始化”。 [英] With Multiple UICollectionView's, getting error, "... must be initialized with non-nil layout"

查看:57
本文介绍了使用多个UICollectionView,获取错误,“...必须使用非零布局初始化”。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆