2011-10-21 3 views
8

私はカスタムセルを持つUITableViewを持っています。 Grand Central Dispatchを使用して画像を非同期に読み込みます。すべて正常に動作しますが、下にスクロールすると、以前に読み込まれた画像が新しい画像がダウンロードされるまで表示されます。私のコードは以下の通りです:GCD UITableView非同期ロードイメージ、新しいイメージのダウンロードまで間違ったセルがロードされる

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

P.P.私は細胞を再利用します

答えて

18

のではなく、使用して戻ってセルを取得し、その後、インデックスパスをキャプチャする必要があるセルをキャプチャ:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 

そうすれば、セルが画面から外れ、今であれば、あなたは背中や画像nilを得るでしょうに間違ったセルには設定されません。

dispatch_async()の後に追加する必要があるものは、cell.imageView.image=somePlaceholderImageです。

例えば:

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

回答ありがとうございます...しかし、いくつかのサンプルコードを提供していただけますか? – blackhawk4152

+0

私の答えを更新しました – hypercrypt

+0

ありがとう、男!ちょうど私が望むもの – blackhawk4152

2

あなたの- (void)tableView:(UITableView *)aTableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {あなたは画像を消去するか、スピナーにリセットする必要があります。テーブルビューの行は再利用されるため、これは表示される動作です。

2

定義のUITableViewCellしません - その目的のために(無効)prepareForReuseを? オーバーライドして、そこの画像ビューを消去します。

+0

[documentation](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableViewCell/prepareForReuse)あなたはprepareForReuseの中のコンテンツに触れてはいけません。代わりにcellForRowAtIndexPathのコンテンツをリセットする必要があります。 –

関連する問題