如何判断UITableViewCell是否已被出队或不在屏幕显示?
实现方案
- 利用UITableViewCell自带的复用生命周期方法
prepareForReuse,这个方法会在cell即将被回收复用时触发,此时直接停止定时器即可。 - 也可以重写
didMoveToWindow方法,当self.window == nil时说明cell已经离开屏幕,此时停止定时器;当self.window != nil时如果定时器未运行,可以重启定时器。 - 额外优化:原有Timer的写法会强持有Cell,导致Cell无法正常释放,建议改用带weak修饰的Block版本Timer避免循环引用。
修改后参考代码:
class TeamBattleTableViewCell: UITableViewCell { @IBOutlet weak var resultsSubtitleLabel: MantisLabel! var timer: Timer? func updateDisplay() { updateTime() // 先停掉旧定时器避免重复创建 timer?.invalidate() // 改用Block版本Timer,加weak self避免循环引用 timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in self?.updateTime() } } @objc func updateTime() { let man = TeamBattleManager.get() let d = man.end_date.offsetFrom(date: Date()) resultsSubtitleLabel.text = d+" remaining" } // 重写复用方法,cell被回收时停止定时器 override func prepareForReuse() { super.prepareForReuse() timer?.invalidate() timer = nil } // 可选:cell离开/进入屏幕时自动处理定时器启停 override func didMoveToWindow() { super.didMoveToWindow() if window == nil { // 离开屏幕,停止定时器 timer?.invalidate() timer = nil } else { // 进入屏幕,按需重启定时器 updateDisplay() } } }
如果你更倾向于在ViewController层面控制,也可以搭配UITableView的两个代理方法实现:在
tableView(_:willDisplay:forRowAt:)里调用cell的updateDisplay启动定时器,在tableView(_:didEndDisplaying:forRowAt:)里调用cell的定时器停止逻辑,两种方案都可以满足需求。
内容的提问来源于stack exchange,提问作者Chase Roberts
相关产品推荐
相关产品推荐

