是否安全,推迟单元的异步图像下载是否有意义?这背后的想法是我希望在创建单元格之后执行来自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
}
答案 0 :(得分:1)
NSHipster有一篇关于如何/何时使用延迟的好文章,here。
我不会以这种方式使用defer
。延迟的目的是在一个代码块中清理/释放内存,而不是将其分散到许多出口点。
考虑在整个函数中使用多个保护语句,并且必须在每个函数中释放内存。
您不应该使用它来简单地在事后添加其他代码。
如@jagveer所述,已有许多第三方库已经这样做,例如SDWebImage缓存。 AFNetworking和AlamoFire也有相同的内置。当它已经完成时,无需重新发明轮子。
答案 1 :(得分:0)
在这种情况下,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
}