Créé par programmation à l'aide d'un UITableViewCell sous-classe en Swift
Je suis en train de travailler sur une vue de la table avec une cellule personnalisé qui a été créé par programmation, sans l'utilisation de l'IB. J'ai regardé sur Google et demandé autour de NSChat, mais je ne peux toujours pas le faire fonctionner. Il affiche juste le défaut d'affichage de tableau. Merci à l'avance!
EventCell.swift
import UIKit
class EventCell: UITableViewCell {
var eventName: UILabel = UILabel()
var eventCity: UILabel = UILabel()
var eventTime: UILabel = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.contentView.addSubview(eventName)
self.contentView.addSubview(eventCity)
self.contentView.addSubview(eventTime)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
eventName = UILabel(frame: CGRectMake(20, 10, self.bounds.size.width - 40, 25))
eventCity = UILabel(frame: CGRectMake(0, 0, 0, 0))
eventTime = UILabel(frame: CGRectMake(0, 0, 0, 0))
}
}
ViewController.swift
class ViewController: UITableViewController, UITableViewDelegate {
var events: Dictionary<String, [String]> = ["0": ["Monroe Family", "La Cañada", "8:30"]]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self;
tableView.delegate = self;
tableView.registerClass(EventCell.self, forCellReuseIdentifier: "EventCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension;
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return events.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cellIdendifier: String = "EventCell"
var cell: EventCell = tableView.dequeueReusableCellWithIdentifier(cellIdendifier, forIndexPath: indexPath) as EventCell
cell = EventCell(style: .Default, reuseIdentifier: cellIdendifier)
if let i = events[String(indexPath.row)] {
cell.eventName.text = i[0]
cell.eventCity.text = i[1]
cell.eventTime.text = i[2]
}
cell.sizeToFit()
return cell
}
}
- github.com/ericcgu/TableViewCellWithAutoLayoutiOS8
- laissez cellIdendifier: String = "EventCell" depuis cellIdentifier n'est pas muté.
- laissez la cellule: EventCell = tableView.dequeueReusableCellWithIdentifier(cellIdendifier, forIndexPath: indexPath) comme! EventCell depuis la cellule n'est pas muté et la force abattu à l'aide !
Vous devez vous connecter pour publier un commentaire.
Ok d'abord quelques observations importantes.
Première, vous êtes inutilement de la création de votre propre nouvelle cellule à chaque fois que l'affichage de la table demande une cellule au lieu de réutiliser les vieilles cellules. Vous devriez supprimer cette ligne:
Qui est inutile parce que la file d'attente va automatiquement créer de nouvelles cellules que nécessaire en fonction de la classe que vous avez enregistré pour l'identifiant donné.
Deuxième, vous ne devriez pas être à l'aide de l'écran principal de limites lors de la pose de votre code. Ce sera briser si votre vue de la table n'est pas toute la largeur. Au lieu de cela, vous pouvez utiliser
self.bounds
il est donc toujours par rapport à la cellule elle-même.Troisième, vous ne devriez pas appeler setNeedsLayout ou layoutIfNeeded parce que si la méthode est appelée, elle est déjà pose à nouveau le tout.
Quatrième, vous devez vous inscrire votre vue de la table de la cellule de la classe avant le réglage de l'affichage de la table de source de données juste au cas où UITableView tout commence en demandant des choses à partir de la source de données lorsque la source de données est définie.
Cinquième, deux de vos sous-vues ont une taille de 0,0 donc ils ne vont pas montrer de toute façon.
Si ce code est en effet en cours d'exécution sans s'écraser, alors vous êtes la création d'EventCells parce que vous faites un forcé casting de la suite de la
dequeueReusableCellWithIdentifier:forIndexPath
. Cela signifie que vous avez simplement une mise en page /affichage /données du problème.init(style:reuseIdentifier:)
. Ensuite, vous pouvez retirer comme normal.dequeueReusableCell(withIdentifier:)
(pas d'index paramètre de chemin d'accès). Cela fonctionne comme vous le décrivez: retourne nil si il veut une nouvelle cellule initialisé. Et cela signifie que vous n'avez plus besoin d'enregistrer la classe avec la tableview à l'avance.J'ai eu la même question. J'ai appliqué les conseils de @drewag réponse, mais il y avait quelques questions supplémentaires. Ci-dessous est un bare-bones, une preuve de concept exemple qui montre comment utiliser un créé par programmation
UITableViewCell
sous-classe.L'image ci-dessous est à quoi il doit ressembler. Les rectangles jaunes sont
UILabel
des sous-vues dans la coutume des cellules.Code
Ici est la UITableViewCell sous-classe. C'est le travail consiste à initialiser la cellule et son contenu, ajouter des sous-vues, et la mise en page de la sous-vues.
Ici est le point de vue du contrôleur de code.
Notes:
UIViewController
plutôt qu'unUITableViewController
. Si vous utilisez unUITableViewController
puis retirez leUITableViewDelegate
etUITableViewDataSource
protocole de références car elles sont redondantes pour uneUITableViewController
. Vous aussi n'avez pas besoin de@IBOutlet tableView
ligne.eventName = UILabel(frame: CGRectMake(...))
. Au lieu de cela, il doit avoir étéeventName.frame = CGRect(...)
Votre code ne fonctionne pas car il est la création de nouveaux UILabels dans EventCell.layoutSubviews. Seulement l'initiale UILabels se sont ajoutés à la vue de l'arbre et leurs tailles sont probablement 0 avais.
Je suppose que vous vouliez mettre à jour leurs cadres, par exemple, mise à jour de la EventCell méthode de classe:
Vous pouvez utiliser paresseux instanciation rapide pour éviter d'avoir à déposer dans layoutSubviews /vue du cycle de vie de la danse.