Les images dans UITableViewCells se chargent incorrectement

Je travaille sur une application où je veux montrer des images, presque aussi grandes que sur des écrans, dans un UITableView avec des cellules personnalisées. Les images se chargent bien, un peu lentement mais elles se chargent, mais quand je défile dans TableView elles apparaissent dans la mauvaise cellule (par exemple Image1 dans Cell5 où Image5 est supposée apparaître) après 1 ou 2 secondes l'image correcte apparaît. Afin de ne pas avoir beaucoup de trafic de données, j'ai pensé à un "cache"-like URL / stockage de l'image comme ceci:

- (id) init { if (self = [super init]) { self.cacheStoreDictionary = [NSMutableDictionary new]; } return self; } - (void) startLoadingImageWithUrl:(NSSsortingng *)urlSsortingng forItem:(id)item { if (self.cacheStoreDictionary[urlSsortingng]) { UIImage *image = self.cacheStoreDictionary[urlSsortingng]; [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:YES]; } else { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithSsortingng:urlSsortingng]]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ [self.cacheStoreDictionary setObject:image forKey:urlSsortingng]; [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO]; }); }); } } 

L'URL et le rest des données dont j'ai besoin sont en cours de chargement via AFNetwork comme ceci:

 - (void)fetchTicketEvents { // Login URL NSURL *eventsURL = [NSURL URLWithSsortingng:TH_API_BASEURL]; AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:eventsURL]; httpClient.parameterEncoding = AFJSONParameterEncoding; // Set request parameters NSDictionary *params = nil; NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:TH_API_PATH_TICKET_EVENT_INDEX parameters:params]; request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; // Prepare request AFJSONRequestOperation *eventsRequest = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { if ([self.delegate respondsToSelector:@selector(thAPITicket:didLoadTicketEvents:response:errorCode:)]) { NSArray *jsonEventArray = JSON; NSMutableArray *event = [[NSMutableArray alloc] initWithCapacity:jsonEventArray.count]; for (NSDictionary *eventDictionary in [JSON allObjects]) { [event addObject:[LCEvent eventFromDictionary:eventDictionary]]; } [self.delegate thAPITicket:self didLoadTicketEvents:YES response:@{@"response" : response, @"json" : JSON, @"event" : event} errorCode:TH_API_ERR_TICKETINDEX_NO_ERROR]; #if LOG_NETWORKING [self printJSON:JSON]; #endif //Network indicator off [LCSharedInstance hideNetworkActivity]; //Allow Slide-To-Refresh [LCSharedInstance singletone].allowSlideToRefresh = YES; [LCSharedInstance singletone].isShownLoadingMessage = NO; [LCSharedInstance singletone].isLoading = NO; } } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { if ([self.delegate respondsToSelector:@selector(thAPITicket:didLoadTicketEvents:response:errorCode:)]) { if (nil == JSON) { JSON = @{}; } [self.delegate thAPITicket:self didLoadTicketEvents:NO response:@{@"response" : response, @"json" : JSON} errorCode:TH_API_ERR_TICKETINDEX_NO_ERROR]; [LCSharedInstance hideNetworkActivity]; } //Network indicator off [LCSharedInstance hideNetworkActivity]; }]; [LCSharedInstance showNetworkActivity]; // Send request [eventsRequest start]; } 

Voici comment je remplis le TableViewCell:

 - (void) lcCachedImageLoader:(LCCachedImageLoader *)cachedImageLoader didLoadImage:(UIImage *)teaserImage forItem:(id)item wasCacheHit:(BOOL)wasCacheHit { //Teaser Image Implementation UIImageView *imageView = ((UIImageView*)[((UIView*)item)viewWithTag:100]); imageView.alpha = 0.2; imageView.image = teaserImage; imageView.contentMode = UIViewContentModeScaleToFill; [UIView animateWithDuration:0.5 animations:^{ imageView.alpha = 1.0; }]; } #pragma mark - tableview delegation - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSSsortingng *CellIdentifier = @"offerCell"; LCEvent *event = self.eventArray[indexPath.row]; tableView = self.tableView; LCClusterViewController *clusterVC = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; #pragma mark - Cell Config and Style Atsortingbutes clusterVC.titleLabel.atsortingbutedText = LCAttrText(event.titleSsortingng, LCFontStyleEventName); clusterVC.ticketDetailsLabel.atsortingbutedText = LCAttrText(event.subtitleSsortingng, LCFontStyleEventTitle); clusterVC.oldPriceLabel.atsortingbutedText = LCAttrText(event.oldPriceSsortingng, LCFontStyleEventOldPrice); clusterVC.actualPriceLabel.atsortingbutedText = LCAttrText(event.actualPriceSsortingng, LCFontStyleEventPrice); clusterVC.timeLabel.atsortingbutedText = LCAttrText(event.timeSsortingng, LCFontStyleEventInfoText); clusterVC.ticketCountLabel.atsortingbutedText = LCAttrText(event.stockSsortingng, LCFontStyleEventInfoText); clusterVC.dateLabel.atsortingbutedText = LCAttrText(event.dateSsortingng, LCFontStyleEventDateText); ... and on and on 

donc merci pour tous les conseils utiles

Les cellules de la vue tableau sont en cours de réutilisation pour des raisons de performance, de sorte qu'elles conservent l'image précédemment utilisée dans UIImageView si vous ne la définissez pas avant de charger l'image.

Juste avant d'appeler startLoadingImageWithUrl, vous pouvez d'abord définir l'image initiale de l'imageView avec une image d'espace réservé ou peut-être append un indicateur de chargement au-dessus de l'imageView. Mais n'oubliez pas d'enlever l'indicateur de chargement lorsque l'image réelle est chargée.

 - (void) startLoadingImageWithUrl:(NSSsortingng *)urlSsortingng forItem:(id)item { UIImageView *imageView = ((UIImageView*)[((UIView*)item)viewWithTag:100]); imageView.image = placeholderImage; if (self.cacheStoreDictionary[urlSsortingng]) { UIImage *image = self.cacheStoreDictionary[urlSsortingng]; [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:YES]; } else { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithSsortingng:urlSsortingng]]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ [self.cacheStoreDictionary setObject:image forKey:urlSsortingng]; [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO]; }); }); } } 

Et pour l'image apparaissant à la mauvaise cellule après le chargement de l'image, c'est parce que vous passez item, qui est la cellule réutilisée, en tant que paramètre dans le startLoadingImage et didLoadImage. Essayez de passer à la place indexPath et searchz la cellule correcte avec l'indexPath, la mise à jour de l'affichage de l'image de la cellule.

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

vous écrivez simplement ce code où vous affectez l'image si elle n'est pas chargée alors

 cell.imageView.image = Nil; 

si elle est chargée, vous affectez l'image si d'autres comme ça

 cell.imageView.image = Nil; if([dictionary objectForKey:@"Image"]) { cell.imageView.image = [dictionary objectForKey:@"Image"]; }else { cell.imageView.image = Nil; }