tldr:使用prepareForReuse 取消现有的网络调用,这些调用可以在下载不同的 indexPath 后完成。对于所有其他意图和目的,只需使用cellForRow(at:。这略微违反了 Apple 文档。但这就是大多数开发人员做事的方式。在两个地方都有单元配置逻辑很不方便......
Apple 文档说用它来重置与内容相关的不属性。然而,根据经验,在cellForRow 内为内容而不是不做所有事情可能更容易。唯一真正有意义的是
从Apple's docs 引用prepareForReuse:
出于性能原因,您应该只重置单元格的属性
与内容无关,例如 alpha、编辑和
选择状态。
例如如果选择了一个单元格,您只需将其设置为未选择,如果您将背景颜色更改为某种颜色,则只需将其重置为 默认 颜色。
tableView(_:cellForRowAt:) 中的 table view 的委托 应该
重用单元格时始终重置所有内容。
这意味着,如果您尝试设置联系人列表的个人资料图像,则不应尝试在 prepareforreuse 中设置 nil 图像,您应该正确地将图像设置在 cellForRowAt 中,如果您没有找到任何图像然后将其图像设置为nil 或默认图像。基本上,cellForRowAt 应该管理预期/意外状态。
所以基本上以下是不建议的:
override func prepareForReuse() {
super.prepareForReuse()
imageView?.image = nil
}
建议使用以下方法:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
cell.imageView?.image = image ?? defaultImage // unexpected situation is also handled.
// We could also avoid coalescing the `nil` and just let it stay `nil`
cell.label = yourText
cell.numberOfLines = yourDesiredNumberOfLines
return cell
}
另外推荐默认的非内容相关项目如下:
override func prepareForReuse() {
super.prepareForReuse()
isHidden = false
isSelected = false
isHighlighted = false
// Remove Subviews Or Layers That Were Added Just For This Cell
}
通过这种方式,您可以放心地假设在运行 cellForRowAt 时,每个单元格的布局都是完整的,您只需要担心内容。
这是 Apple 建议的方式。但老实说,我仍然认为像马特所说的那样,将所有内容都倾倒在cellForRowAt 中更容易。干净的代码很重要,但这可能并不能真正帮助您实现这一目标。但是作为Connor said,唯一需要的是,如果您需要取消正在加载的图像。更多内容见here
即做类似的事情:
override func prepareForReuse() {
super.prepareForReuse()
imageView.cancelImageRequest() // this should send a message to your download handler and have it cancelled.
imageView.image = nil
}
另外在使用 RxSwift 的特殊情况下:
见here或here