当为每个 UITableViewCell 运行 Timer 时,它们没有被正确回收

Posted

技术标签:

【中文标题】当为每个 UITableViewCell 运行 Timer 时,它们没有被正确回收【英文标题】:When a Timer is running for each UITableViewCell, they are not being recycled properly 【发布时间】:2016-12-22 22:12:26 【问题描述】:

我有一个 UITableView,其中每个单元格都有一个标签。当在单元格上按下按钮时,我需要每 0.01 毫秒更新每个单元格的标签。

func tick(label: UILabel) 
    let timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true)  (timer) in
        // functionality to decide what to put in the label goes here
        label.text = "some string"
    



// button action
@IBAction func startButtonPressed(_ sender: UIButton) 
    let buttonPostion = sender.convert(CGPoint.zero, to: tableView)

    if let indexPath = tableView.indexPathForRow(at: buttonPostion), let cell = tableView.cellForRow(at: indexPath) as? CustomCell 
        tick(label: cell.label)
    

我遇到的问题是,当我滚动 UITableView 时,单元格没有被正确回收。例如,如果我单击顶部单元格上的开始按钮,计时器开始运行并且其标签将开始更改,然后如果我向下滚动另一个单元格的标签也将更改为与顶部单元格相同,没有它的计时器正在启动。

解决此问题的最佳方法是什么?

【问题讨论】:

作为@Tom Harrington 的答案的替代方案,我建议将您的计时器与您的数据源结合起来。 【参考方案1】:

听起来细胞被正确地重复使用了。单元重用的想法是,当UITableViewCell 的一个实例滚出屏幕时,当另一端需要一个新单元时,会再次使用该实例。您正在一个单元格中启动一个计时器,该单元格被重用,并且因为它是同一个对象,所以它具有相同的计时器,该计时器已经在运行。如果您设计一个具有某种状态的单元格(例如,一个正在运行的计时器),则需要在该单元格被重用时重置该状态,否则它将保持不变。

如果您要在单元格中保留计时器,则需要安排在重复使用单元格时停止并重新启动计时器。您可以通过在表格单元格类中覆盖prepareForReuse 来停止计时器——这样当一个单元格被重用时,就永远不会有一个正在运行的计时器。要重新启动它们,您必须让表视图数据源跟踪哪些单元格有正在运行的计时器,以便您可以在使单元格出列时启动计时器。

【讨论】:

以上是关于当为每个 UITableViewCell 运行 Timer 时,它们没有被正确回收的主要内容,如果未能解决你的问题,请参考以下文章

我的 UITableViewCell 正在重用以前的单元格 UIImage

优化 UITableViewCell 上的绘图

UITableViewCell 扩展自动布局

NSAutoresizingMaskLayoutConstraint 的 UITableViewCell 舍入错误,但在 Storyboard 和 heightForRowAtIndexPath 中正

在屏幕下方加载时,UITableViewCell 按钮单击未注册

iOS 11 中的 UITableViewCell 转换中断