UITableViewCells中的图像加载错误

我正在一个应用程序,我想要显示图像,几乎一样大的屏幕大小,在自定义单元格的UITableView。 图像加载良好,虽然速度有点慢,但是会加载,但是当我在TableView中滚动时,它们会在1或2秒后显示在错误的单元格中(例如Image5在应该显示Image5的单元格中),出现正确的图像。 为了不需要很多数据stream量,我想到了像这样的“caching”式URL /图像存储:

- (id) init { if (self = [super init]) { self.cacheStoreDictionary = [NSMutableDictionary new]; } return self; } - (void) startLoadingImageWithUrl:(NSString *)urlString forItem:(id)item { if (self.cacheStoreDictionary[urlString]) { UIImage *image = self.cacheStoreDictionary[urlString]; [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 URLWithString:urlString]]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ [self.cacheStoreDictionary setObject:image forKey:urlString]; [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO]; }); }); } } 

URL和我需要的其余数据我通过AFNetwork加载,如下所示:

 - (void)fetchTicketEvents { // Login URL NSURL *eventsURL = [NSURL URLWithString: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]; } 

这里是我如何填写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 NSString *CellIdentifier = @"offerCell"; LCEvent *event = self.eventArray[indexPath.row]; tableView = self.tableView; LCClusterViewController *clusterVC = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; #pragma mark - Cell Config and Style Attributes clusterVC.titleLabel.attributedText = LCAttrText(event.titleString, LCFontStyleEventName); clusterVC.ticketDetailsLabel.attributedText = LCAttrText(event.subtitleString, LCFontStyleEventTitle); clusterVC.oldPriceLabel.attributedText = LCAttrText(event.oldPriceString, LCFontStyleEventOldPrice); clusterVC.actualPriceLabel.attributedText = LCAttrText(event.actualPriceString, LCFontStyleEventPrice); clusterVC.timeLabel.attributedText = LCAttrText(event.timeString, LCFontStyleEventInfoText); clusterVC.ticketCountLabel.attributedText = LCAttrText(event.stockString, LCFontStyleEventInfoText); clusterVC.dateLabel.attributedText = LCAttrText(event.dateString, LCFontStyleEventDateText); ... and on and on 

所以谢谢任何有用的提示

由于性能上的原因,表格视图单元格被重用,所以如果在加载图像之前没有将其设置为任何内容,它们将保留以前在UIImageView中使用的图像。

在调用startLoadingImageWithUrl之前,可以先使用占位符图像设置imageView的初始图像,或者在imageView的顶部添加加载指示器。 但是请记住在加载实际图像时删除加载指示符。

 - (void) startLoadingImageWithUrl:(NSString *)urlString forItem:(id)item { UIImageView *imageView = ((UIImageView*)[((UIView*)item)viewWithTag:100]); imageView.image = placeholderImage; if (self.cacheStoreDictionary[urlString]) { UIImage *image = self.cacheStoreDictionary[urlString]; [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 URLWithString:urlString]]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ [self.cacheStoreDictionary setObject:image forKey:urlString]; [self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO]; }); }); } } 

加载图像后出现在错误的单元格中的图像,是因为您正在传递作为重用单元格的项目作为startLoadingImage和didLoadImage中的参数。 尝试传递indexPath,并使用indexPathfind正确的单元格,更新单元格图像视图。

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

如果没有加载的话,你只需要在这个代码分配的地方写代码

 cell.imageView.image = Nil; 

如果它加载,那么你分配的图像,如果没有这样的

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