swift 定时器初始化/失效

bksxznpy  于 2023-01-25  发布在  Swift
关注(0)|答案(2)|浏览(123)

我尝试在用户按下返回按钮时取消初始化/使Timer无效,但在他按下下下一个ViewController时没有。

var timer = Timer()
                timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timePrinter), userInfo: nil, repeats: true)
                timer.fire()

override func viewWillDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    if self.isMovingFromParentViewController{
        timer.invalidate()
    }
}

当用户按下返回按钮时,它不工作。

xriantvc

xriantvc1#

当你使用一个带有“target/selector”的计划计时器时,它会保留它的目标。更具体地说,Runloop会保留计划计时器,而计划计时器也会保留它们的目标。
我使用这个版本,它不保留self:

Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in
    self?.doSomethingRegularly()
})

而且您还需要在deinit中使上述计时器无效,否则您将泄漏计时器(但不会泄漏 * 您的 * 类)。

bpzcxfmw

bpzcxfmw2#

编辑

Martin R提出了一个很好的观点:计时器将保存对视图控制器的强引用,因此我将timer.invalidate()放在视图控制器的deinit()方法中的建议行不通。
Chris建议使用闭包版本的Timer可以解决这个问题,所以你可以把timer.invalidate()调用放在视图控制器的deinit()方法中,所以你也应该像Chris的回答那样重写你的定时器代码。
-————————————-
不要在viewWillDisappear(_:)中放置timer invalidate。创建一个deinit方法并放在那里。当你按下返回按钮时,当前的视图控制器应该被释放,deinit方法将被触发。

deinit {
  timer.invalidate()
}

相关问题