GCD UITableView异步加载图像,加载错误的单元格直到新图像下载

时间:2011-10-21 15:54:39

标签: objective-c ios cocoa-touch uitableview

我有一个带自定义单元格的UITableView。我使用Grand Central Dispatch异步加载图像。一切正常,但是当我向下滚动时,会显示先前加载的图像,直到下载新图像。这是我的代码:

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

任何建议表示赞赏。 附:我重用了单元格

3 个答案:

答案 0 :(得分:18)

不是捕获您需要捕获索引路径的单元格,而是使用以下方式恢复单元格:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

这样一来,如果单元格现在不在屏幕上,你将无法返回,并且图像不会设置在错误的单元格上。

dispatch_async()cell.imageView.image=somePlaceholderImage之后,您需要添加的另一件事。

E.g:

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

答案 1 :(得分:2)

- (void)tableView:(UITableView *)aTableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {中,您需要清除图像,或将其重置为您的微调器。由于表视图行被重用,这就是您将看到的行为。

答案 2 :(得分:2)

UITableViewCell是否为此目的定义 - (void)prepareForReuse? 覆盖它并在那里清除你的imageView。