2013-05-22 47 views
8

我正在使用自定義單元格在UITableView中顯示幾乎與屏幕大小一樣大的圖像的應用程序。 圖像加載良好,但有點慢,但是當它們在TableView中滾動時,它們在1或2秒後出現在錯誤的單元格中(例如Image5在應該顯示Image5的單元格中),顯示正確的圖像。 爲了不有許多datatraffic我想過一個「緩存」般的URL /或圖像存儲這樣的:UITableViewCells中的圖像加載錯誤

- (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 

十分感謝任何有用的提示

回答

3

表視圖細胞被指定圖像因爲性能原因而重用,所以如果您在加載圖像之前未將其設置爲任何內容,它們將保留之前在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,並使用indexPath找到正確的單元格,更新單元格圖像視圖。

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

+0

是的,我試過了太多,但它使整個imageloading慢,並沒有真正解決問題。一些圖片在短時間內仍處於錯誤的位置。 – d3p0nit

+0

你在哪裏調用startLoadingImageWithUrl:(NSString *)urlString forItem:(id)item? –

+0

在我的cellForRowAtIndexpath結尾處: – d3p0nit

1

您只需編寫代碼,你指定圖像,如果它沒有加載那麼

cell.imageView.image = Nil; 

如果它加載,然後你如果別人這樣

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

}else 
{ 
    cell.imageView.image = Nil; 
}