使用延迟在 UITableViewCell 上延迟图像下载

Posted

技术标签:

【中文标题】使用延迟在 UITableViewCell 上延迟图像下载【英文标题】:Lazy image downloading on UITableViewCell using defer 【发布时间】:2016-09-12 07:58:00 【问题描述】:

推迟一个单元格的异步图像下载是否安全?是否有意义?这背后的想法是我希望 URLSession.shared.image(...) 的回调函数在创建单元格后执行,并且只有一次调用 cellForRow(at: indexPath) 是有效的,因为我认为没有推迟这个方法此时应该返回 nil。

URLSession.shared.image 是一个私有扩展,它运行数据任务并仅在参数中提供的 url 有效且包含图像时才提供转义回调。

setImage(image:animated) 是一个私有扩展,允许您使用简单的动画在 UIImageView 中设置图像。

如果延迟不是办法,请指明替代方案。

感谢任何反馈,谢谢!

override func tableView(_ tableView: UITableView, cellForRowAt
    indexPath: IndexPath) -> UITableViewCell 

    let cell = baseCell as! MyCell
    let datum = data[indexPath.row]
    cell.imageView.setImage(placeholderImage, for: .normal)

    defer 
        URLSession.shared.image(with: datum.previewURL)  image, isCached in
            if let cell = tableView.cellForRow(at: indexPath) as? MyCell 
                cell.imageView.setImage(image, animated: !isCached)
            
        
    

    return cell

【问题讨论】:

你是否为它尝试了 SDWebImage 第三方 【参考方案1】:

NSHipster 有一篇关于如何/何时使用 defer 的好文章,here。

我不会以这种方式使用defer。 defer 的目的是在一个代码块中清理/释放内存,而不是将其分散到多个退出点。

考虑在一个函数中使用多个保护语句,并且必须在每个函数中释放内存。

您不应该在事后简单地使用它来添加额外的代码。

正如@jagveer 所提到的,有许多第三方库已经这样做了,例如 SDWebImage 缓存。 AFNetworking 和 AlamoFire 也具有相同的内置功能。已经完成后无需重新发明***。

【讨论】:

【参考方案2】:

在这种情况下,defer 无效。 defer 设置一个块以在范围退出时调用,您将立即执行此操作。

我认为您希望使用Dispatch 安排块在不同的线程中运行。你需要回到主线程来更新 UI。

由于这可能会在以后发生,因此您需要确保该单元格仍在用于相同的条目,并且在用户进一步滚动时没有被重复使用。如果它已被重用,那么再次获取单元格不是一个好主意,因为您最终会再次触发初始调用。我通常会在自定义 UITableViewCell 类中添加一些标识符以进行检查。

另外,您不是在创建单元格,而是从其他变量中获取它。如果有多个单元格,这可能是个问题。

override func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell 

    let cell = tableView.dequeueReusableCell(withIdentifier: "base") as! MyCell
    cell.row = indexPath.row
    let datum = data[indexPath.row]
    cell.imageView.setImage(placeholderImage, for: .normal)

    DispatchQueue.global().async 
        // Runs in a background thread
        URLSession.shared.image(with: datum.previewURL)  image, isCached in
            DispatchQueue.main.async 
                // Runs in the main thread; safe for updating the UI
                // but check this cell is still being used for the same index path first!
                if cell.row == indexPath.row 
                    cell.imageView.setImage(image, animated: !isCached)
                
            
        
    

    return cell

【讨论】:

以上是关于使用延迟在 UITableViewCell 上延迟图像下载的主要内容,如果未能解决你的问题,请参考以下文章

在 uitableviewcell 中激活 uislider 的延迟时间

如何从 UITableViewCell 中的自定义 UIButton 中删除触摸延迟

图像模糊前略有延迟

在 UITableView 中使用带有 [UIImage resizableImageWithCapInsets] 的 UIImageView 会导致延迟

UITableView 延迟加载问题

UITableView 中多张图片的延迟加载