通过 dispatch_async 获取图像数据后刷新 UITableViewCell

Posted

技术标签:

【中文标题】通过 dispatch_async 获取图像数据后刷新 UITableViewCell【英文标题】:Refreshing UITableViewCell after fetching image data by dispatch_async 【发布时间】:2014-12-09 18:00:35 【问题描述】:

我正在编写显示 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];

并且没有显示图像,但是当我单击单元格或滚动整个列表时,会显示图像。为什么我的视图不刷新?我错过了什么吗?

【问题讨论】:

使用一些框架来下载异步图像会容易得多。比如 SDWebImage github.com/rs/SDWebImage 然后你只需要写[cell.imageView sd_setImageWithURL:[NSURL urlWithString:@"http://somelink.png"]] 【参考方案1】:

在单元格上调用 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()
    

【讨论】:

【参考方案2】:

您可以随时通过调用 [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中每次都创建一个

【讨论】:

这导致调用 cellForRowAtIndexPath: 的循环结束,因为你想刷新它,它调用了这个方法。 你可以缓存图像并使用它。尝试查看 NSCache 的临时缓存。【参考方案3】:

这可能与从后台队列与 UI 交互有关。试试这个:

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];
    );
);

【讨论】:

不,这不起作用,单击或滚动后会显示静止图像:/

以上是关于通过 dispatch_async 获取图像数据后刷新 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

Apple Watch Kit 无法获取图像

使用 dispatch_async 在 UICollectionView 中加载图片

dispacth_sync vs dispatch_async:iOS JSON 解析

NSManagedObjectContext performBlock 内的 dispatch_async(dispatch_get_main_queue()

dispatch_get_global_queue vs dispatch_get_main_queue

coredata + MagicRecords,如何在后台查找All