J’a i les plus grandes peines du monde pour réussir à faire avaler à Xcode un modèle de prototype de celllule de UITableView pour un petit jeu à la con . Il y a dans ce prototype 4 UIImageView de petite taille et un label. Il se noie avec, refuse de suivre les contraintes et me superpose le label et les imageviews ou bien refuse de reconnaître la subclass de UITableViewCell que j’ai fini par faire pour essayer de l’amadouer. Je suis sur Mojave, avec Xcode 10.1 pour cette appli, et non pas sur Catalina avec Xcode 11.4.1. Mais je suis au bord de la reddition ou du fichier xib pour voir…
Voici le bout de code qui coince :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) → UITableViewCell {
tableView.register( Celle.self, forCellReuseIdentifier:« Celle »)
// c’est la ligne que voici qui coince :
let cell:Celle = tableView.dequeueReusableCell(withIdentifier:« Celle », for: indexPath) as! Celle
/* je précise que Celle est le nom de la cellule prototype dans le storyboard, mais aussi le nom de la sous-classe de UITableViewCell que j’ai créée pour connecter les imageViews et le label */
// print(« case recherchée : (hitsPlayed[indexPath.row][0]) »)
var name = hitsPlayed[indexPath.row]
cell.image1?.image = UIImage(named: name[0])
cell.image2?.image = UIImage(named: name[1])
cell.image3?.image = UIImage(named: name[2])
cell.image4?.image = UIImage(named: name[3])
cell.textLabel!.text = hitsPlayed[indexPath.row][4]
return cell
}
Voici aussi une copie d’écran d’un bout du storyboard
Commence peut-être par renommer ta classe CelleTableViewCell ou quelque chose du genre pour différencier la classe de l’identifier de ta cellule.
D’expérience, c’est jamais bon de nommer pareil deux choses différentes.
Mais dans ce cas, certes, il n’y aura pas de crash, mais je resterai grosjean comme devant et ma cellule ne se peuplera pas de ce qu’elle doit. Mon problème n’est pas de gérer un optionnel. Cela ne résoud pas mon problème. Je dois savoir pourquoi il considère la cellule retournée comme vide et non pourvue des imageView et label dont elle est sensée être pourvue. C’est ça que je n’arrive pas à trouver.
Mon code a beaucoup changé depjis hier soir, car j’essaye des trucs, j’ai même tenté de coller ma cellule prototype dans un nib. Mais les essais passent, l’erreur, reste, au même endroit, ce qui montre un défaut sans doute assez global et facile à corriger, quand on sait. Moi, je sèche. voilà l’image de mon .xib :
le code de ma classe :
class CelleTableViewCell: UITableViewCell {
@IBOutlet weak var tryLabel: UILabel!
@IBOutlet weak var image1: UIImageView!
@IBOutlet weak var image2: UIImageView!
@IBOutlet weak var image3: UIImageView!
@IBOutlet weak var image4: UIImageView!
static let reuseIdentifier = "Cellela"
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUpObjects()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpObjects()
}
private func setUpObjects(){
contentView.addSubview(image1)
contentView.addSubview(image2)
contentView.addSubview(image3)
contentView.addSubview(image4)
contentView.addSubview(tryLabel)
}
}
et enfin, le bout de code dans lequel se produit l’erreur :
let theNib = UINib.init(nibName: "Cellela", bundle: nil)
mytableView.register(theNib, forCellReuseIdentifier: "Cellela")
mytableView.register(CelleTableViewCell.self, forCellReuseIdentifier: "Cellela")
let cell:CelleTableViewCell = tableView.dequeueReusableCell(withIdentifier:"Cellela", for: indexPath) as! CelleTableViewCell
var name = hitsPlayed[indexPath.row]
cell.image1!.image = UIImage(named: name[0]) //"unexpectedly found nil while unwrapping an optional(image1)"
cell.image2!.image = UIImage(named: name[1])
cell.image3!.image = UIImage(named: name[2])
cell.image4!.image = UIImage(named: name[3])
cell.tryLabel!.text = name[4]
return cell
}
Je ne doute pas de n'être qu'un con fini, mais au moins… déconfiné
J’aimerai bien ! Mais non, il contient un nom d’image valide, qui a déjà servi à remplir une autre imageView, c’est image1, l’imageView, qui pointe sur nil (d’après debug) :
Je suis encore moins compétent en SwiftUI qu’en UIKit ; je ne suis pas enclin à croire qu’on puisse corriger une ignorance ici par une incompétence ailleurs. Quand j’aurais compris ce qui ne va pas et que je l’aurais corrigé, je m’en rappellerai avec SwiftUI que j’apprendrai plus vite, non ?
À moins que j’aie tout faux et que tu sois en mesure de me démontrer que ça irait beaucoup plus vite …
Démontrer … je ne connais pas encore assez bien l’outil pour faire ça. Mais sincèrement je pense que SwiftUI est vraiment un énorme pas en avant pour les novices (et les autres).
Environ une heure de travail (y compris la réalisation des magnifiques ressources graphiques, réalisées à la MAIN sur un iPad Pro). Et c’était la première fois que je créais une cellule personnalisée et même une liste en SwiftUI !
Tu as tout à fait raison, après avoir erré dans les sept cercles de l’enfer…
J’ai trouvé la solution ! J’ai cessé de retourner aux anciens fichiers .xib, de compliquer des classes effectivement auxquelles manquent les contraintes, de surcharger des fonctions qui n’en ont pas besoin, et de faire compliqué quand on peut faire simple !
la classe de la cellule prototype :
class CelleTableViewCell: UITableViewCell {
@IBOutlet weak var tryLabel: UILabel!
@IBOutlet weak var image1: UIImageView!
@IBOutlet weak var image2: UIImageView!
@IBOutlet weak var image3: UIImageView!
@IBOutlet weak var image4: UIImageView!
}
et rien d’autre !
et dans le même fichier que le ViewController, hors de sa classe, pour éviter d’en faire une classe intégrée ;
Du coup, dans le ViewController :
Un code un peu plus simple, aéré et lisible. Et ça marche. Je découvre tes suggestions un peu après la bataille, mais si j’avais pu les lire il y a deux jours, je ne sais pas si j’aurais compris ; là, ça fait sens pour moi, et je te remercie d’avoir pris le temps de lire mon code un peu pourri et de m’avoir conseillé aussi juste et aussi aimablement ! Merci, ristretto.
C’est écœurant, ton truc. En une heure. Évidemment, je comprends ce que tu veux dire, passer à SwiftUI, oui, oui, oui… Bon, je finis de dernier truc en UIKit, et je décroche, c’est sûr. Mais j’imagine bien qu’avant d’en arriver à faire ça en une heure, il a fallu une certaine courbe d’apprentissage qui n’a pas dû ne prendre aucune durée, hein ? Combien de temps que tu es sur SwiftUI ? Six mois ?
Beaucoup moins que ça. Je me suis réellement mis à SwiftUI il y a environ 1 mois, en bricolant un peu et regardant à nouveau les vidéos de Maxime et d’un de ses collègues sur Udemy.
Mais je fait partie de ces gens qui ne peuvent apprendre qu’en faisant des choses par eux-mêmes. J’ai besoin d’un objectif précis à accomplir. J’ai réellement compris les principes de base en réalisant une version SwiftUI de la calculatrice UIKit de Maxime.
J’ai présenté cette première réalisation dans ce topic, il y a 15 jours :
Depuis, je cherche des idées de projet pour avancer : un p’tit jeu, un convertisseur décimal/binaire/hexa, ton problème de cellules personnalisées, etc …
La courbe d’apprentissage de SwiftUI est très rapide, pour quelqu’un connaissant déjà Swift.