prepareForReuse 的正确使用方法是什么?

What is the correct way to use prepareForReuse?

在了解如何在 UIKit 中使用 prepareForReuse() 方面需要帮助。 documentation 表示

you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state

但是如何重置个别 属性 属性,例如 isHidden?

假设我的单元格有 2 个标签,我应该在哪里重置:

  1. label.text
  2. label.numberOfLines
  3. label.isHidden

我的 tableView(_:cellForRowAt:) 委托具有每个单元格 hide/show 个标签的条件逻辑。

如文档所述,您只需使用上述方法重置与内容无关的属性即可。至于重置标签的 text/number 行...,您可以在设置新值之前从 tableView(_:cellForRowAt:) 中进行重置,如下所示:

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

    cell.label.text = "" //reseting the text
    cell.label.text = "New value"
    return cell
    }

您可以采用更面向对象的方法并创建 UITableViewCell 的子类并定义一个方法,比如 configureCell() 来处理新出列单元格的所有重置和值设置。

tldr:使用 prepareForReuse 取消现有的网络调用,这些调用可以在下载不同的 indexPath 后完成。对于所有其他意图和目的,只需使用 cellForRow(at:。这与 Apple 文档略有冲突。但这就是大多数开发人员做事的方式。两处都有cell配置逻辑很不方便...


Apple 文档说使用它来重置与 content 相关的 not 属性。然而,根据经验,只在 cellForRow 内为内容做所有事情可能更容易,而不是。唯一真正有意义的时间是

引用 Apple's docsprepareForReuse:

For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state.

例如如果一个单元格被选中,你只需将它设置为未选中,如果你将背景颜色更改为某种颜色,那么你只需将其重置回其 默认 颜色。

The table view's delegate in tableView(_:cellForRowAt:) should always reset all content when reusing a cell.

这意味着如果您尝试设置联系人列表的个人资料图片,则不应尝试 prepareforreuse 中的 nil 图片,您应该在 [=21] 中正确设置图片=],如果您没有找到任何图像 ,则 您将其图像设置为 nil 或默认图像。基本上 cellForRowAt 应该管理 expected/unexpected 状态。

所以基本上下面是的建议:

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推荐的方式。但老实说,我仍然认为像 Matt 所说的那样将所有内容都转储到 cellForRowAt 中更容易。干净的代码很重要,但这可能并不能真正帮助您实现这一目标。但是作为 the only time it's necessary is, if you need to cancel an image that is loading. For more see 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 的特殊情况下: 参见 or here