J'analyse un JSON dans ma méthode viewDidLoad. L'une des clés de ce JSON est l'URL de l'image, qui va dans un tableau de chaînes appelé "allCImages"
Ceci est juste une chaîne. Par conséquent, pour remplir l'image dans la cellule, dans ma méthode cellForRowAt, j'ai ce qui suit:
extension UIImageView { func downloadImage(from imgURL: String!) { let theUrl = URLRequest(url: URL(string: imgURL)!) // set initial image to nil so it doesn't use the image from a reused cell image = nil // check if the image is already in the cache if let imageToCache = vc1ImageCache.object(forKey: imgURL! as NSString) { self.image = imageToCache print("Image is in Cache") return } // download the image asynchronously let task = URLSession.shared.dataTask(with: theUrl) { (data, response, error) in if error != nil { print(error!) return } DispatchQueue.main.async { // create UIImage let imageToCache = UIImage(data: data!) // add image to cache vc1ImageCache.setObject(imageToCache!, forKey: imgURL! as NSString) self.image = imageToCache } } task.resume() }
Remarque: vcCellImage est l'IBOutlet de la vue d'image de ma cellule.
La méthode "downloadImage" fait partie de l'extension suivante:
cell.vcCellImage.downloadImage(from: allCImages[indexPath.section])
Cela fonctionne presque parfaitement . Par exemple:
1) Si je fais défiler lentement ma vue de tableau, toutes les cellules contiennent l'image correcte
2) Si je fais défiler mon tableau, lentement ou rapidement, toutes les cellules contiennent l'image correcte. Cela est prouvé par le fait que ma console imprime ce qui suit:
Ie, la tableview obtient mon image du cache (puisque pour faire défiler vers le haut, je dois avoir fait défiler vers le bas avant)
3) Le problème est que je fais défiler mon tableau très rapidement, dès la première tentative. Comme l'image n'a pas encore été mise en cache, la cellule affichera la mauvaise image, avant de passer à l'image correcte. Problème classique
Par conséquent, il me manque ce petit morceau de logique. Comment résoudre ce problème?
EDIT: j'ai essayé ceci mais le problème demeure:
classe VCTableViewCell: UITableViewCell {
override func prepareForReuse () {super.prepareForReuse () vcCellImage.image = nil}
3 Réponses :
J'ai été confronté à un problème similaire. J'ai résolu ce problème en annulant la demande d'image dans la méthode prepareForReuse . Pouvez-vous essayer la même chose?
J'ai essayé mais le problème persiste: - class VCTableViewCell: UITableViewCell {override func prepareForReuse () {super.prepareForReuse () vcCellImage.image = nil}
hé @SteveJobs définissant l'image sur nil ne fonctionne pas, vous devez annuler l'URLRequest.
Ici, vous pouvez créer une variable de tâche URLSession de tâche dans VCTableViewCell et stocker la tâche pour chaque cellule correspondante, puis préparer la réutilisation do task.cancel ()
Cela se produit à cause de
1- retrait de la cellule: les cellules sont réutilisées à l'intérieur du tableau
2- lorsque vous faites défiler avant qu'une requête ne se produise, cela peut provoquer un nouveau 1 avec la même URL
La meilleure option consiste à utiliser SDWebImage
tout d'abord si vous ajoutez votre API ou des données comme celle-ci, supprimez simplement ceci
var arr = [string]() viewWillAppear() { arr.removeAll() //call api //append Data arr.append("s","sd","sd) }
accepte cela
var arr = [string]() viewDidLoad() { arr.append("s","sd","sd) }
J'ai un problème similaire alors je le résous comme ça, cela peut être utile pour vous aussi.