2011-10-21 13 views
8

Mam UITableView z komórkami niestandardowymi. Obrazy są asynchronicznie ładowane za pomocą Grand Central Dispatch. Wszystko działa dobrze, ale kiedy przewijam w dół, wcześniej załadowane obrazy są wyświetlane do momentu pobrania nowego obrazu. Oto mój kod:GCD UITableView obrazy obciążenia asynchronicznego, nieprawidłowe komórki są ładowane do momentu pobrania nowego obrazu

if (![[NSFileManager defaultManager] fileExistsAtPath:[path stringByAppendingPathComponent:@"image.png"]]) 
{ 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
    dispatch_async(queue, ^{ 
     NSString *url=[pat stringByAppendingPathComponent:@"comments.txt"]; 
     NSString *u=[NSString stringWithContentsOfFile:url encoding:NSUTF8StringEncoding error:nil]; 
     NSURL *imageURL=[NSURL URLWithString:u]; 
     NSData *image=[NSData dataWithContentsOfURL:imageURL]; 
     [image writeToFile:[pat stringByAppendingPathComponent:@"image.png"] atomically:YES]; 
     dispatch_sync(dispatch_get_main_queue(), ^{ 
      cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; 
      [cell setNeedsLayout]; 
      NSLog(@"Download"); 
     }); 
    }); 
} 
else 
{ 
    NSLog(@"cache"); 
    cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; 
} 

Wszelkie sugestie doceniane. P.S. Ponownie wykorzystuję komórki

Odpowiedz

18

Zamiast przechwytywania komórkę trzeba zarejestrować ścieżkę indeksu, a następnie uzyskać komórkę z powrotem przy użyciu:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 

ten sposób, jeśli komórka jest teraz poza ekranem dostaniesz nil powrotem i obraz nie zostanie ustawione na niewłaściwej komórce.

Kolejną rzeczą, którą należy dodać po dispatch_async(), jest cell.imageView.image=somePlaceholderImage.

Np .:

if (![[NSFileManager defaultManager] fileExistsAtPath:[path stringByAppendingPathComponent:@"image.png"]]) 
{ 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
    dispatch_async(queue, ^{ 
     NSString *url=[pat stringByAppendingPathComponent:@"comments.txt"]; 
     NSString *u=[NSString stringWithContentsOfFile:url encoding:NSUTF8StringEncoding error:nil]; 
     NSURL *imageURL=[NSURL URLWithString:u]; 
     NSData *image=[NSData dataWithContentsOfURL:imageURL]; 
     [image writeToFile:[pat stringByAppendingPathComponent:@"image.png"] atomically:YES]; 
     dispatch_sync(dispatch_get_main_queue(), ^{ 
      UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
      cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; 
      [cell setNeedsLayout]; 
      NSLog(@"Download"); 
     }); 
    }); 
    cell.imageView.image=[UIImage imageNamed:@"placeholder"]; 
} 
else 
{ 
    NSLog(@"cache"); 
    cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; 
} 
+0

dzięki za odpowiedź ... ale czy mógłbyś podać przykładowy kod? – blackhawk4152

+0

Zaktualizowano moją odpowiedź – hypercrypt

+0

dzięki, stary! Właśnie to, co chciałem – blackhawk4152

2

Musisz wyczyścić obraz lub zresetować go do swojej przędzarki. Ponieważ wiersze widoku tabeli są ponownie wykorzystywane, jest to widoczne zachowanie.

2

Nie UITableViewCell zdefiniować - (void) prepareForReuse do tego celu? Zastąp go i wyczyść obraz. Wyświetl tam.

+0

Zgodnie z [dokumentacją] (http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableViewCell/prepareForReuse) nie powinieneś dotykać zawartości wewnątrz prepareForReuse. Zamiast tego należy zresetować zawartość w komórceForRowAtIndexPath. –

Powiązane problemy