UITableView, photos et gestion de mémoire

Bonjour à  tous !


 


J'ai une TableView avec des photos.


Le problème est la gestion de la mémoire. En effet, les photos prennent beaucoup de place.


Ce que je souhaite faire, c'est vider la mémoire au fur et à  mesure que l'utilisateur fait défiler la TableView.


 


Le problème est que je ne sais pas comment faire.


 


J'ai déjà  réussi à  charger les images au fur et à  mesure que l'on affiche les rows, avec le code suivant :



func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: TableCell.identifier, for: indexPath) as! TableCell
cell.photos.image = nil
}

Et ça fonctionne ! Au lancement, je suis à  60 Mo, et lorsque j'ai vu toutes les images, je suis à  150... Et j'ai encore plein d'image à  rajouter...


 


J'ai essayé d'utiliser la fonction willDisplay, mais ça ne fonctionne pas, et les images ne sont tout simplement pas chargées.



func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: TableCell.identifier, for: indexPath) as! TableCell
cell.showPhotos(id: data[indexPath.row].id)
}

Je vous remercie pour votre aide !


Réponses

  • CéroceCéroce Membre, Modérateur

    Il te faut un cache d'images. Tu pourrais le programmer toi-même, par exemple à  l'aide de NSCache, mais c'est beaucoup plus de travail qu'il n'y parait. En pratique, il y a beaucoup de subtilités à  régler.


     


    Aussi, je te conseille d'utiliser une bibliothèque déjà  écrite. Par exemple:


    https://github.com/stxnext/STXImageCache


  • LeChatNoirLeChatNoir Membre, Modérateur

    Après, méfiance.... Il ne faut pas chercher à  optimiser une appli tant que tu n'as pas de pb de perfs...


     


    Donc finalise déjà  ton truc et tu verras si y a vraiment besoin de s'y pencher. Dans 90% des cas, y a pas besoin.


     


    Le dequeue devrait suffire.

  • DrakenDraken Membre
    novembre 2017 modifié #4

    On avait vu ce genre de choses avec le MOOC du prof Kordon (que tu ferais bien de visionner un de ces jours - voir ma signature).


    A chaque chargement d'une UIImage, iOS conserve les données graphiques dans un tampon afin d'éviter de la recharger plus tard. Même si tu crois détruire une image en mettant sa valeur à  nil, elle est quand même archivée.


     


    L'astuce c'est de charger l'image avec la méthode imageWithContentsOfFile qui ne stocke pas l'image dans le tampon.


     


    Ce n'est pas aussi simple à  utiliser qu'un chargement classique, la méthode ayant besoin de connaà®tre l'emplacement du fichier image dans le bundle pour la charger en mémoire. J'ai écrit une extension (Swift 3) pour gérer ça facilement. Cela ne fonctionne qu'avec des images jpg, mais le code est facile à  modifier pour gérer le png.


    a



    // Chargement UIImage sans passer par un cache
    extension UIImage {
    static func chargerSansBuffer(nom:String) -> UIImage? {
    if let fileURL = Bundle.main.url(forResource: nom, withExtension :"jpg") {
    return UIImage(contentsOfFile: fileURL.path)
    }
    return nil
    }
    }

    a


    Je te recopie une partie d'un message que j'ai rédigé sur le forum du MOOC.


     


    Kordon :


     



     


     


    Dans UIImage, vous avez deux méthodes. Le "init" classique qui garde les images en cache à  des fins d'accélération (mais cela a un impact sur la mémoire utilisée) et imageWithContentsOfFile: qui n'utilise pas le cache. Dans certains cas (dont celui de l'imagier) la seconde solution peut éviter des crashs lorsque les images sont (volontairement) lourdes.

     


     


    Moi :


     



     


     


    Ah oui, j'avais complètement oublié cette histoire de chargement d'images sans cache. J'ai modifié mon Imagier (Swift) pour comparer la charge mémoire dans les deux cas. La différence est impressionnante ! J'ai 13 images dans mon application, occupant 12,3 Mo sur le disque, au format jpg. Au bout d'un cycle de lecture avec un UIImage(named:String), la charge mémoire est de 156 Mo. Ces qui n'est pas illogique, iOS gardant les images sous une forme non-compactée en mémoire. Même procédure avec un chargement utilisant UIImage(contentsOfFile:String). La charge mémoire monte et descend lors du test, sans dépasser 60 Mo. A la dernière image, elle se stabilise à  environ 30 Mo !  Passer de 156 Mo à  30 Mo c'est pas mal, même si cela oblige l'application à  recharger les images en totalité à  chaque lecture !

  • Joanna CarterJoanna Carter Membre, Modérateur
    Regardes mon appli Fest Jazz https://itunes.apple.com/fr/app/fest-jazz/id1130028470?mt=8. Tu trouves là  dedans les listes avec les images. Je n'ai rien fait que mettre les images dans Assets. Pas d'optimisation, ça va sans souci
  • Je vous remercie pour vos réponses !


     


    Je vais regarder tout cela et continuer !


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