8
votes

Mauvaise image CollectionView Image de la cellule lors du téléchargement et de la sauvegarde de fichiers async avec achèvementblock

Je me rends compte qu'il y a déjà beaucoup de ces questions, mais aucun d'entre eux ne semble aborder cette affaire.

La collectionView lit les noms de fichiers à partir de Fichiers TRAY et chargent des images du répertoire de documents ou les télécharge, affiche et enregistre les documents. Fonctionne parfaitement lisse et sans aucune bibliothèque supplémentaire, mais lors du défilement rapide, plusieurs cellules reçoivent de mauvaises images. Appeler [collectionView reloaddata] avec n'importe quelle action ou défilement recharge ces mauvaises images à des bonnes images à bonnes.

J'imagine que c'est lié à la réutilisation des cellules avec l'attribution d'une image ASYNC, mais comment résoudre ce problème? CollectionView et cellule personnalisée définie dans le storyboard. Les images sont stockées sur le serveur derrière l'authentification de base, de sorte que la plupart des solutions de réutilisation ne s'appliquent pas. xxx

J'ai essayé de nombreuses modifications, mais aucun d'entre eux ne semble résoudre le problème. Actuellement, l'effet est que les nouvelles cellules apparaissant lors du défilement rapide sont changées plus d'une fois et certaines d'entre elles se retrouvent toujours avec une image erronée, pointant dans une question de réutilisation.

Merci d'avance pour toute aide et suggestions .


0 commentaires

3 Réponses :


13
votes

Vous devez conserver des informations contextuelles quelque part. En d'autres termes, dans votre bloc d'achèvement, vérifiez si la cellule doit vraiment contenir une image téléchargée ou non. Sinon, ne l'attribuez pas. Par exemple URL d'image. Vous pouvez faire cela ...

  • Ajouter une propriété nsurl * imageURL à votre objet cellulaire
  • Avant votre Downloadfromurl: ... Store fileurl à imageURL Propriété de la cellule
  • Dans le bloc d'achèvement, comparez si fileurl correspondent cell.ImageURL et s'il correspond à l'image, définissez l'image sinon ne le définit pas
  • et nil Votre cellule imageURL propriété dans Prépareforruse

    ... ou vous pouvez déplacer votre code de chargement dans votre classe de cellules et attribuer ici une URL de l'image, etc. De nombreuses façons de le faire.


5 commentaires

Fonctionne génial, merci! J'utilise la propriété Imagename pour cette comparaison et cela résout le problème.


Ou utiliser @rob Way. Et ajoutez ce qu'il suggère (annulation, mise en cache, ...).


@ROBERTVOJTA Je vois que les vérifications d'Afnetworking pour la même URL, tandis que SDwebimage ne


Enregistré ma semaine (une journée et 1/2) frapper la tête contre CocheForitematidExpath retourner nul pour (très) cellules visibles. Je m'attends à ce que cette réponse soit fermée bientôt pour empêcher toute fin, merci ;-)))))))))))))))))))))))))))))))))


Pareil ici. Merci beaucoup!



15
votes

Le problème est que lors du défilement rapide, la cellule peut être déséquilibrée et réutilisée pour une autre cellule au moment de la fin de la demande asynchrone, à la mise à jour de la mauvaise cellule. Donc, dans votre bloc d'achèvement, vous devez vous assurer que la cellule est toujours visible: xxx

Remarque, ce uicollectionview méthode CELFEFORITEMATINDEXPATH ne devrait pas être confondu avec le uicollectionvievation de la même manière Méthode CollectionView: CORELFORITEMATINDEXPATH: . La méthode uicollectionview CORELFORITEMATDEXPATH renvoie un uicollectionviewcell Si la cellule est toujours visible et renvoie nil si ce n'est pas le cas.

Au fait, le ci-dessus suppose que le nsindexpath de cette cellule ne peut pas changer (c'est-à-dire qu'il n'est pas possible que des lignes supplémentaires auraient pu être insérées au-dessus de cette ligne tandis que l'image était asynchroneusement récupéré). Ce n'est parfois pas une hypothèse valide. Donc, si vous vouliez faire attention, ce que vous devriez vraiment faire, c'est de retourner au modèle et de recalculer ce que le nsindexpath pour cet objet modèle, et utilisez-le pour déterminer le updateCell Référence.


Idéalement, une fois que vous avez adressé ce qui précède, il y a quelques optimisations que vous pourriez apporter à ce processus:

  1. Si la cellule est réutilisée pendant que la requête précédente est toujours en cours d'exécution, vous voudrez peut-être annuler cette demande préalable. Si vous ne le faites pas et que vous faites défiler rapidement, disons, 200 cellules, affichez-vous maintenant, par exemple, les cellules 201 à 221, les demandes de ces 20 cellules actuellement visibles seront en file d'attente et ne s'affichera pas tant que les demandes de 200 demandes précédentes.

    Pour pouvoir annuler des demandes antérieures, vous ne pouvez pas utiliser sendasynchronousrequest . Vous devez utiliser un NsurlConnection ou NsurlSessionTask , qui sont annulables.

  2. Vous devez probablement mettre en cache vos images. Si vos cellules actuellement visibles ont toutes leurs images et que vous les faites défiler, vous sortez, vous semblez les demander à nouveau. Vous devriez d'abord voir si vous avez déjà récupéré l'image, et dans l'affirmative, utilisez-le, et seulement si vous n'en avez pas dans votre cache, réémunérez la demande.

    Oui, je sais que vous utilisez la version du fichier dans le stockage persistant vers le cache, mais vous pouvez également vouloir mettre en cache à RAM. Généralement, les gens utilisent nscache à cette fin.

    C'est beaucoup à changer. Si vous voulez de l'aide, faites-nous savoir. Mais beaucoup plus facilement consiste à utiliser la catégorie uiimageview dans SDWebimage ou Afnetworking , qui fait tout cela pour vous.


5 commentaires

Merci, ça marche! Ad 1. J'ai rencontré un problème avec NsurlConnection - je pense que c'était un problème de mise à jour des images cellulaires tout en défilant. AD 2. Je vais y examiner, merci.


@yosh très bien. RE "AD 1", je ne suggérais pas d'utiliser NsurlConnection pour répondre à votre question initiale, mais faire une observation totalement indépendante qu'il permettrait des demandes annulables, et si vous annulez les demandes en attente de Les cellules qui ont défilé hors de vue, il améliorera grandement les performances si vous faites défiler vraiment rapidement avec une connexion Internet lente. Désolé si cette observation non sollicitée était une source de confusion!


Inutile de s'excuser. Je crois comprendre que je ne comprends pas comment implémenter NsurlConnection qui satisferait également les fonctionnalités ci-dessus, car j'avais un problème avec cela auparavant.


@yosh Ouais, c'est un peu compliqué. Pas la science de la fusée, mais non triviale, aussi. C'est pourquoi j'ai suggéré la catégorie uiimageview de SDwebimage , car ils ont fait un bon bon travail avec une mise en œuvre assez élégante. (Je suis un fan Afnetworking, mais la catégorie UIImageView de SDWebimage est un peu plus fort que Afnetworking's, IMHO, donc à moins que vous n'utilisez déjà Afnetworking pour d'autres raisons, SDwebimage est probablement la voie à suivre.)


Ça ne marche pas pour moi. J'utilise plutôt quelque chose comme ça si cell.Id == imageURL {} Pour vérifier si la cellule est la même cellule, l'image ASYNC Chargement a commencé.



2
votes

Vous devez faire référence à la cellule en bloc de remplacement: xxx

avec xxx


0 commentaires