我会建议:
-
不要实例化空的Timer
。考虑:
var timer = Timer()
那就是创建一个空白的计时器实例。我们不想这样做。你应该使用:
weak var timer: Timer?
这实现了一些目标:
-
The pepe
方法签名不太正确:
启动和停止计时器没有意义init
.
该参考().self
in the target
应该只是self
.
-
在你的操场上,你正在停止计时器(尚未安排启动)然后启动它。
您可能还想在一段时间后停止它,这样您就有机会看到Timer
在行动中。
-
但是,作为一般规则,在编写启动计时器的方法时,请谨慎确保您没有(意外地)启动它。如果您不这样做,并且不小心调用了startTimer
两次,最终可能会导致多个计时器同时运行(最糟糕的是,丢失了对较早计时器的引用)。一种常见的解决方案典型的解决方案是查看是否已有计时器,如果有,则在创建下一个计时器之前将其无效。这可以通过可选的链接模式轻松完成:
func startTimer() {
timer?.invalidate() // stops previous timer, if any
// now proceed with scheduling of new timer
}
Thus:
import UIKit
// if doing this in playground, include the following two lines
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
// MyClass
public class MyClass {
weak var timer: Timer?
@objc func timerHandler(_ timer: Timer) {
let hola = "hola"
print(">>>> \(hola)")
}
func startTimer() {
timer?.invalidate() // stops previous timer, if any
let seconds = 1.0
timer = Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(timerHandler(_:)), userInfo: nil, repeats: true)
}
func stopTimer() {
timer?.invalidate()
}
}
var object = MyClass()
object.startTimer()
// stop it 10 seconds later
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
object.stopTimer()
}
不过,应该认识到,您最终可能会得到类似于强引用循环的东西:
- runloop 保留对预定计时器的强引用;
- 基于选择器的计时器对其保持强引用
target
;
- The
MyClass
(the target
) 可能是导致该计时器最终失效的原因。
因此,MyClass
不能被释放,直到Timer
无效。而且,就目前情况而言,你不能只是invalidate
the Timer
in the deinit
of MyClass
, 因为deinit
在计时器失效之前不会被调用。
最终效果是,如果你有,例如,这个MyClass
作为视图控制器的属性并启动计时器,然后关闭视图控制器,计时器将继续运行并且MyClass
不会被释放。
为了解决这个问题,您可能需要使用基于闭包的计时器[weak self]
参考,消除了定时器和之间的强参考MyClass
。然后,您还可以在以下情况下自动使计时器无效:MyClass
被释放:
public class MyClass {
weak var timer: Timer?
deinit {
timer?.invalidate()
}
func timerHandler(_ timer: Timer) {
let hola = "hola"
print(">>>> \(hola)")
}
func startTimer() {
timer?.invalidate() // stops previous timer, if any
let seconds = 1.0
timer = Timer.scheduledTimer(withTimeInterval: seconds, repeats: true) { [weak self] timer in
self?.timerHandler(timer)
}
}
func stopTimer() {
timer?.invalidate()
}
}