GCD UITableView асинхронная загрузка изображений, неправильные ячейки загружаются до загрузки нового изображения - PullRequest
8 голосов
/ 21 октября 2011

У меня есть 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"]];
}

Любые предложения приветствуются.PS я повторно использую клетки

Ответы [ 3 ]

18 голосов
/ 21 октября 2011

Вместо того, чтобы захватывать ячейку, вам нужно захватить путь индекса, затем вернуть ячейку, используя:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

Таким образом, если ячейка теперь не на экране, вы вернете ноль, и изображение не будет установлено не на ту ячейку.

Другая вещь, которую вам нужно добавить после 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"]];
}
2 голосов
/ 25 октября 2011

Разве UITableViewCell не определяет - (void) prepareForReuse для этой цели?Переопределите его и очистите ваш imageView там.

2 голосов
/ 21 октября 2011

В вашем - (void)tableView:(UITableView *)aTableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { Вам необходимо очистить изображение или сбросить его на счетчик.Поскольку строки табличного представления используются повторно, это поведение вы увидите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...