Affichage d'images dans une cellule

heliohelio Membre
octobre 2015 modifié dans API UIKit #1

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.


Réponses

  • Joanna CarterJoanna Carter Membre, Modérateur
    Et tu mets ce code où ?
  • LarmeLarme Membre
    octobre 2015 modifié #3

    À 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.


  • DrakenDraken Membre
    octobre 2015 modifié #4

    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.




    if varRealise.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) == "true" {

    let imageNameR = "Realise.png"
    let imageR = UIImage(named: imageNameR)
    cell.imageView.image = imageR
    cell.imageView.frame = CGRect(x: 250, y: 45, width: 25, height: 25)

    } else if varNonRealise.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) == "true" {
    let imageNameN = "NonRealise.png"
    let imageN = UIImage(named: imageNameN)
    cell.imageView = imageN
    cell.imageView.frame = CGRect(x: 250, y: 45, width: 25, height: 25)
    } else {
    let frame1 = CGRectMake(250,45,26,26)
    cell.imageView.frame = frame1
    cell.imageView.backgroundColor = UIColor.whiteColor()
    }



    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.

  • Joanna CarterJoanna Carter Membre, Modérateur
    octobre 2015 modifié #6

    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.


  • DrakenDraken Membre
    octobre 2015 modifié #7

    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. 

  • Joanna CarterJoanna Carter Membre, Modérateur

    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é.




  • C'est visible à  tous sur vidéo 411 de WWDC 2015, vers 21' , même pour les débutants :)




    Depuis quand Apple fait des choses simples dans ces tutos techniques ?

  • Joanna CarterJoanna Carter Membre, Modérateur
    octobre 2015 modifié #11


    Faire simple .. c'est trop compliqué !

    Faire compliqué .. c'est si simple !

    Swift .. c'est simple !

    ;)
Connectez-vous ou Inscrivez-vous pour répondre.