tutorial source how data collection ios swift uicollectionview

ios - source - uicollectionview swift 3 programmatically



Con Multiple UICollectionView''s, obteniendo el error, "... debe inicializarse con un diseƱo no nulo" (2)

Recientemente comencé a trabajar con Swift, y estoy tratando de pasar de un UICollectionView en la página (que funcionó) hasta dos de ellos. Estoy recibiendo el error

" Aplicación de finalización debido a excepción no detectada '' NSInvalidArgumentException'', razón: ''UICollectionView debe inicializarse con un parámetro de diseño no nulo ''".

Lo que he encontrado hasta ahora en Stack Overflow se ha incorporado a mi código, pero sigo recibiendo el error. Estoy al final de mi ingenio, ¡por favor ayuda!

Donde he estado:

  • Comencé con este artículo sobre la configuración de UICollectionView y todo funcionó bien.
  • Ahora para configurar un segundo UICollectionView en la misma pantalla, seguí las instrucciones de este artículo .
  • Todo parece estar bien, obtengo "Build Succeeded" (Construir con éxito), seguido de un accidente cuando la aplicación comienza a ejecutarse. Mensaje de error dice:

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

  • Buscando el error en StackOverflow, encuentro este artículo (que trata de un solo UICollectionView, en lugar de los dos que tengo).
  • Implementé todo lo que pude de ese artículo, pero sigo recibiendo el error y ahora no tengo ideas. Mi código está debajo, ¡cualquier ayuda sería muy apreciada!

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! }


No asigne objetos UICollectionView vacíos a sus propiedades; los va a descartar de todos modos y está causando la excepción ya que no está proporcionando un diseño. Esta es una situación en la que puede usar una opción opcional sin encriptar implícitamente:

var collectionViewLeft: UICollectionView! var collectionViewRight: UICollectionView!


Supongo que declaras UICollectionViewController ''s con el constructor init vacío vacío como variables:

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

Intenta reemplazar tus declaraciones de variables sin constructores:

Código editado a continuación: Como @ Paulw11 señaló correctamente en su respuesta a continuación, ¡es mejor utilizar una opción opcional implícitamente desenvuelta! más bien que ?

var collectionViewLeft: UICollectionView! var collectionViewRight: UICollectionView!

De todos modos, se viewDidLoad una instancia en la función viewDidLoad con los inicializadores designados para UICollectionView .

Y solo una nota, es mejor registrar clase personalizada / xibs antes de UICollectionView como una subvista. No es crítico en este momento, pero puede ser un problema después de la refactorización, etc., ya que el código puede llamar UICollectionView delegate dataSource o a dataSource funciones de dataSource antes de codificar las clases personalizadas registradas para las celdas. Simplemente mueva su código con llamadas a .register() arriba de self.view.addSubview() :

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