Affichage d'images dans une cellule
Bonsoir à tous,
Dans une tableView, j'ai le code suivant qui me permet d'afficher une image dans une cellule en fonction de la valeur des variables varRealise ou varNonRealise (valeurs true ou false) :
if let user = KeychainService.loadToken() as? String {
if varRealise.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) == "true" {
let imageNameR = "Realise.png"
let imageR = UIImage(named: imageNameR)
let realiseImageView = UIImageView(image: imageR!)
realiseImageView.frame = CGRect(x: 250, y: 45, width: 25, height: 25)
cell.contentView.addSubview(realiseImageView)
} else if varNonRealise.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) == "true" {
let imageNameN = "NonRealise.png"
let imageN = UIImage(named: imageNameN)
let nonRealiseImageView = UIImageView(image: imageN!)
nonRealiseImageView.frame = CGRect(x: 250, y: 45, width: 25, height: 25)
cell.contentView.addSubview(nonRealiseImageView)
} else {
let frame1 = CGRectMake(250,45,26,26)
let imageView1 = UIImageView(frame: frame1)
imageView1.backgroundColor = UIColor.whiteColor()
cell.contentView.addSubview(imageView1)
}
}
Le souci est qu'après plusieurs scroll, cela affiche les images dans n'importe quelle cellule.
Pourtant si j'affiche les valeurs true ou false, elles sont dans les bonnes cellules.
Comment remédier à ce problème ?
Merci.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
À vue d'nez, je dirais que c'est un problème de reuse de cellule.
On évite en général d'ajouter des subviews aux cellules comme tu le fais.
Soit tu créées un custom cell avec déjà son UIImageView à laquelle tu settes l'image ou la cache, soit au moment de fournir les infos de la cell (tableView:cellForRowAtIndexPath:), tu passes en revue toutes les subview et supprimes les inutiles (comme les UIImageView). Note qu'il y a aussi la possibilité dans un custom UITableViewCell de faire des trucs dans le prepareForReuse (en bref, de la remettre à zéro avant réutilisation).
Imagine qu'au lieu d'avoir une longue liste de cellules les unes après les autres, elles bouclent.
C'est à dire que dès que l'une disparait de l'écran, il y en a potentiellement une qui va réapparaitre de l'autre bout. Afin d'éviter d'allouer 50 milles vues, et bien iOS réutilise celle qui vient de sortir, telle quelle. Donc si tu lui a rajouté une vue, elle l'a encore en mémoire. Cela ne se voit pas forcément au départ, car au début, on change souvent le titleLabel ou le subtitleLabel, mais on le fait pour tous dans tableView:cellForRowAtIndexPath:. Cette notion de reuse peut-être occulté dans l'apprentissage à ce niveau là , mais il existe bel et bien.
J'ai eu exactement le même problème. J'ajoutais une imageView au contentView à chaque nouvelle cellule. Et paf .. apparition d'images parasites et explosion de la consommation mémoire. Je pensais au début que le mécanisme de recyclage des cellules les remettait à zéro avant de les réutiliser. Grossière erreur comme j'ai pu le constater. A chaque réutilisation d'une cellule, j'avais une nouvelle vue dans la contentView. Au bout de quelques minutes d'aller et retour dans la tableView j'avais des cellules avec des dizaines de vue dans le contentView. Pas top pour l'affichage !
Une cellule réutilisable peut avoir n'importe quel contenu provenant de "sa vie précédente". Comme le signale Larme, il est possible de redéfinir la méthode prepareForReuse pour remettre la cellule dans son état virginal, mais il y a plus simple.
Pour toi, le plus efficace est de créer une nouvelle classe dérivant de UITableViewCell, en lui ajoutant une imageView, pour pouvoir la personnaliser ensuite à la demande.
J'ai écrit le code de mémoire, sans le tester, juste pour te donner une idée.
Petite rectification. N'ayant pas utilisé les UITableView depuis longtemps (je suis plutôt UICollectionView), j'avais oublié qu'il y avait déjà une propriété imageView dans une UITableViewCell (style par Default). Tu peut t'en servir pour tes affichages, si tu ne l'utilises pas déjà pour autre chose.
Bonjour Helio
En plus de ce que Larme a dit, tu as répété beaucoup de code en créant l'ImageView, ce qui n'est pas du tout nécessaire si tu utilisais un XIB et une classe pour la cellule.
Tu trouveras ci-joint un petit projet qui démontre des idées pour améliorer, voir réduire, ton code.
Nounours, ton code me parait bien compliqué à appréhender par un développeur novice. C'est du code pro, notamment l'encapsulation des images png dans une extension de UIImage.
C'est visible à tous sur vidéo 411 de WWDC 2015, vers 21' , même pour les débutants
Merci à tous pour les explications.
et aussi à Joanna Carter pour le code !
mon problème est réglé.
Depuis quand Apple fait des choses simples dans ces tutos techniques ?