异步提取已完成:是否仍在显示单元格?

时间:2017-02-22 08:29:16

标签: ios objective-c swift asynchronous

在最近的一次采访中,我被问到像#9这样的场景,这些问题涉及将图像异步下载到表格视图单元格中。我理解在cellForIndexPath和异步中调用它的必要性但是我很难过如何在异步调用完成后查看单元格是否仍在视图中(参见下面的第3章摘录)。换句话说,在异步调用之后,如何确定我正在获取数据的表格单元格是否仍在视图中。

  

当为单元格下载图像时,我们需要检查该单元格   仍在视野中或是否已被另一件作品重复使用   数据的。如果它被重新使用,那么我们应该丢弃图像,   否则我们需要切换回主线程来改变   细胞上的图像。

2 个答案:

答案 0 :(得分:2)

您应该在后台开始使用回调机制下载图像,该机制可以决定图片在加载后是否仍然显示。

一个选项是子类UIImageViewUITableViewCell,并存储对图像的NSURL的引用。然后,当您调用回调时,您可以检查图像视图或单元格的缓存URL是否是您拥有的图像之一,并决定是否显示它。

我不建议:

  • 依赖于视图的标记,因为它需要NSURL和整数之间的某种关联表,这需要一个管理器对象,并且无助于代码的可重用性
  • 依赖于单元格的indexPath,因为当网络请求发生时,可能会对其他索引路径重用的表进行更新

Associated Objects, by NSHipster中描述了更高级的选项:

  

在扩展内置类的行为时,可能需要跟踪其他状态。这是关联对象的教科书用例。例如,AFNetworking在其UIImageView类别上使用关联对象来存储请求操作对象,用于异步获取特定URL的远程图像。

答案 1 :(得分:1)

您可以使用以下UITableViewCell方法检查UITableView是否仍在视图中:

//返回可见的indexPaths

var indexPathsForVisibleRows: [IndexPath]?

不检查是否重新加载特定行,您可以使用以下方法执行此操作:

func downloadImageForCell(indexPath: IndexPath) {

    // Asynchronous download method here

    // After download is completed. Call the below in mainqueue
    if let indexPaths:[IndexPath] = self.tableView.indexPathsForVisibleRows {
       // the above line checks if indexPath is available
       if indexPaths.contains(indexPath) {
           self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
       }
    }
}

如果您在实施此代码时遇到任何问题,请与我们联系