2013-05-22 14 views
8

Ich arbeite an einer App, wo ich Bilder, fast so groß wie Bildschirmgröße, in einem UITableView mit benutzerdefinierten Zellen anzeigen möchte. Die Bilder laden gut, ein bisschen langsam, aber sie laden, aber wenn ich in der TableView blättern erscheinen sie in der falschen Zelle (zum Beispiel Image1 in Cell5 wo Image5 erscheinen soll) nach 1 oder 2 Sekunden erscheint das korrekte Bild. Um nicht viele datatraffic ich über einen „Cache“ -ähnlichen URL/Bildspeicherung wie gedacht zu haben:Bilder in UITableViewCells werden falsch geladen

- (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]; 
      }); 
     }); 
    } 
} 

Die URL und der Rest der Daten, die ich brauche ich über AFNetwork wie das Laden :

- (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]; 
} 

Hier ist, wie ich die TableViewCell füllen:

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

so Vielen dank für jeden hilfreichen Hinweis

Antwort

3

Ansicht Zellen die Tabelle geladen werden geladen Sie werden aus Gründen der Leistung erneut verwendet, damit das zuvor verwendete Bild in UIImageView beibehalten wird, wenn Sie es vor dem Laden des Bildes nicht auf einen Wert setzen.

Kurz bevor Sie startLoadingImageWithUrl aufrufen, können Sie das anfängliche Image von imageView zuerst mit einem Platzhalterbild festlegen oder den Ladeindikator oben auf dem imageView hinzufügen. Aber vergessen Sie nicht, den Ladeindikator zu entfernen, wenn das reale Bild geladen ist.

- (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]; 
      }); 
     }); 
    } 
} 

Und für das Bild an der falschen Zelle nach dem Bild erscheinen geladen, es ist, weil Sie Artikel sind vorbei, die Zelle wieder verwendet wird, als Parameter in den startLoadingImage und didLoadImage. Versuchen Sie stattdessen, indexPath zu übergeben und suchen Sie die richtige Zelle mit dem IndexPath, um die Zellenbildansicht zu aktualisieren.

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

+0

Ja Ich habe versucht, das auch, aber es machte die ganze imageloading langsamer und nicht wirklich das Problem lösen. Einige der Bilder sind für eine kurze Zeit immer noch auf falschen Positionen. – d3p0nit

+0

Wo rufst du startLoadingImageWithUrl an: (NSString *) urlString forItem: (id) item? –

+0

am Ende meines cellForRowAtIndexpath: – d3p0nit

1

Sie einfach diesen Code schreiben, wo Sie das Bild zuweisen, wenn es nicht dann

cell.imageView.image = Nil; 

wenn es ordnen Sie dann das Bild, wenn sonst wie diese

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

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