Обновление UITableViewCell после извлечения данных изображения с помощью dispatch_async

Я пишу приложение, которое показывает TableView с записями, которые содержат изображения. Я пытаюсь получить изображение, выполнив эту строку кода внутри cellForRowAtIndexPath метод:

cell.detailTextLabel.text =  [artistData objectForKey:generesKey];
dispatch_async(backgroundQueue, ^{
         NSURL *url_img = [NSURL URLWithString:[artistData objectForKey:pictureKey]];
        NSData* data = [NSData dataWithContentsOfURL:
                         url_img];
        cell.imageView.image = [UIImage imageWithData:data];
        [self performSelectorOnMainThread:@selector(refreshCell:) withObject:cell waitUntilDone:YES];
    });

После настройки изображения я выполняю селектор, который содержит:

-(void)refreshCell:(UITableViewCell*)cell{
    [cell setNeedsDisplay];
    [self.view setNeedsDisplay];
    [self.tableViewOutlet setNeedsDisplay];
}

И изображение не отображается, но когда я нажимаю на ячейку или прокручиваю весь список, изображения отображаются. Почему мой вид не освежает? Я что-то пропустил?

3 ответа

Решение

Вы всегда можете перезагрузить ячейку, позвонив [self.tableView reloadRowsAtIndexPaths@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

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

 NSCache *imageCache = [[NSCache alloc] init];
 imageCache.name = @"My Image Cache";
 UIImage *image = [imageCache objectForKey:url_img];
 if (image) {
    cell.imageView.image = image;
 } else {
    // Do your dispatch async to fetch the image.

    // Once you get the image do
    [imageCache setObject:[UIImage imageWithData:data] forKey:url_img];
}

Вам нужно, чтобы imageCache был свойством на уровне ViewController. Не создавайте один каждый раз вcellForRowAtIndexPath

Должно быть достаточно позвонить setNeedsLayout() на камеру.

В Swift 4 это выглядит так:

DispatchQueue.global().async {
    let data = try? Data(contentsOf: URL(string: imageUrl)!)
    DispatchQueue.main.async {
        cell.imageView?.image = UIImage(data: data!)
        cell.setNeedsLayout()
    }
}

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

dispatch_async(backgroundQueue, ^{
    NSURL *url_img = [NSURL URLWithString:[artistData objectForKey:pictureKey]];
    NSData* data = [NSData dataWithContentsOfURL:url_img];
    dispatch_async(dispatch_get_main_queue(), ^{
        cell.imageView.image = [UIImage imageWithData:data];
    });
});
Другие вопросы по тегам