Créer une UICollectionViewCell
personnalisée pour ma UICollectionViewController
, cela fonctionne en enregistrant le nib; cependant, ne parvient pas à s'inscrire par classe.
Utilisation de registerClass () - échoue
L'enregistrement par classe semble correct - il est construit, mais lève une exception lors de l'exécution en décompressant les éléments optionnels de UIView. Sans référencer les points de vente, il fonctionne; cependant, aucune cellule n'apparaît dans la vue de collection.
collectionView?.registerClass(MyCollectionViewCell.self,
forCellWithReuseIdentifier: "myCell")
Clairement la vue n'est pas chargée; Cependant, je pense que la définition de la classe personnalisée de la cellule fournirait le lien nécessaire.
Utilisation de registerNib () - fonctionne
L'enregistrement par nib fonctionne, ce qui a du sens car il charge explicitement la vue.
let nib = UINib(nibName: "MyCollectionViewCell", bundle: nil)
collectionView?.registerNib(nib, forCellWithReuseIdentifier: "myCell")
Ici, la vue est explicitement référencée et une classe personnalisée est définie pour la vue; Cependant, quelque chose à ce sujet semble faux.
En isolant le problème dans un exemple de projet, vous trouverez ci-dessous les vues et le code à répliquer; ou, ce projet est disponible sur GitHub .
Main.storyboard
Mon contrôleur de vue initiale du storyboard principal est un UICollectionViewController
sous-classé comme MyCollectionViewController
:
MyCollectionViewController.Swift
Affichage des inscriptions par nib et par classe:
import UIKit
class MyCollectionViewController: UICollectionViewController {
var data = [String]()
override func viewDidLoad() {
super.viewDidLoad()
data = ["a", "b", "c"]
// This works, by nib
let nib = UINib(nibName: "MyCollectionViewCell", bundle: nil)
collectionView?.registerNib(nib, forCellWithReuseIdentifier: "myCell")
// This fails, by class
//collectionView?.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "myCell")
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCollectionViewCell
cell.title.text = data[indexPath.row]
return cell
}
}
MyCollectionViewCell.xib
La vue est une UICollectionViewCell
subdivisée en MyCollectionViewCell
avec une UILabel
:
Dans ma nib, l'identifiant identificateur de vue de collection réutilisable a été défini sur: myCell
:
MyCollectionViewCell.Swift
Définit la classe et a une variable IBOutlet
à l'étiquette:
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var title: UILabel!
}
En utilisant le nib, l'exécution apparaît comme:
Pourquoi ne puis-je pas enregistrer UICollectionViewCell
par classe?
De plus, je suis un peu confus quant à savoir si la cellule prototype doit rester sur le contrôleur de vue de la collection de storyboard principale. Là, je n’ai défini aucun identifiant de vue réutilisable.
Je vois ce lien Vue d'ensemble de la collection
Si la classe de cellules a été écrite en code, l'enregistrement est effectué à l'aide de la méthode registerClass: de UICollectionView. Par exemple: [self.myCollectionView registerClass: [MyCollectionViewCell class] pourCellWithReuseIdentifier: @ "MYCELL"]; Si la cellule est contenue dans un fichier NIB d'Interface Builder, la méthode registerNib: est utilisée à la place.
Donc, votre cellule de collecte crée avec nib, vous devez vous inscrire avec nib. Si votre cellule est totalement écrite en code, vous devrez vous inscrire auprès de la classe.
J'espère que cette aide.
En fait, si vous enregistrez la classe dans le scénario et lui attribuez un identifiant de réutilisation, vous ne devriez pas enregistrer sa classe ou sa nib en code.
si vous définissez une cellule à partir d'un fichier NIB, le système choisira le fichier NIB pour instancier la cellule. Si vous ne définissez aucun fichier nib (totalement géré par le code), la cellule doit être initiée par le
- initWithStyle:reuseIdentifier:
méthode . Lorsque vous utilisez
- dequeueReusableCellWithIdentifier:
la méthode - awakeFromNib
sera appelée si vous utilisez nib pour conserver la vue; else
- initWithStyle:reuseIdentifier:
sera appelé.
Ce n'est pas collectionview qui échoue ici. Votre classe personnalisée contient une étiquette implicitement non emballée, définie comme ceci,
@IBOutlet weak var title: UILabel!
Et c'est la raison de l'échec. Où l'instanciez-vous? Et vos méthodes de sources de données sont appelées ce qui est comme ça,
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCollectionViewCell
cell.title.text = data[indexPath.row]
return cell
}
Là, vous essayez de définir du texte sur cette propriété titre qui est nul, ce qui bloque votre application.
Initialisez votre étiquette dans collectionView initWithFrame: method si vous l’utilisez dans un code qui devrait être corrigé.
Ajoutez ce code à votre sous-classe de cellules lors de l'utilisation de in code,
class MyCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var title: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
let title = UILabel(frame: CGRectZero)
title.translatesAutoresizingMaskIntoConstraints = false;
contentView.addSubview(title)
self.title = title
title.topAnchor.constraintEqualToAnchor(contentView.topAnchor).active = true
title.leftAnchor.constraintEqualToAnchor(contentView.leftAnchor).active = true
self.backgroundColor = UIColor.redColor()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}