我们不暂停/恢复Timer
实例。我们阻止他们invalidate() https://developer.apple.com/documentation/foundation/timer/1415405-invalidate。当你想重新启动它时,只需创建新的计时器即可。
请参阅the Timer文档 https://developer.apple.com/documentation/foundation/timer,也可以直接在 Xcode 中使用。
请注意,您可以suspend https://developer.apple.com/documentation/dispatch/dispatchobject/1452801-suspend and resume https://developer.apple.com/documentation/dispatch/dispatchsourceprotocol/1781015-resumeGCD定时器,DispatchSourceTimer https://developer.apple.com/documentation/dispatch/dispatchsourcetimer.
var timer: DispatchSourceTimer? // note, unlike `Timer`, we have to maintain strong reference to GCD timer sources
func createTimer() {
timer = DispatchSource.makeTimerSource(queue: .main)
timer?.schedule(deadline: .now(), repeating: 1.0)
timer?.setEventHandler { [weak self] in // assuming you're referencing `self` in here, use `weak` to avoid strong reference cycles
// do something
}
// note, timer is not yet started; you have to call `timer?.resume()`
}
func startTimer() {
timer?.resume()
}
func pauseTiemr() {
timer?.suspend()
}
func stopTimer() {
timer?.cancel()
timer = nil
}
请注意,我并不是建议如果您愿意suspend
and resume
你应该使用GCDDispatchSourceTimer
。呼唤invalidate
并重新创造Timer
as need 很简单,所以就这么做吧。我只是为了完整起见才提供此 GCD 信息。
顺便说一句,作为一般原则,永远不要“增加”计时器处理程序中的某些计数器。这是一个常见的错误。计时器不能保证每次都会触发或精确度准确。始终在开始时保存一些参考时间,然后在事件处理程序中计算当前时间和开始时间之间的差异。例如,扩展我的 GCD 计时器示例:
func createTimer() {
timer = DispatchSource.makeTimerSource(queue: .main)
timer?.schedule(deadline: .now(), repeating: 0.1)
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
formatter.zeroFormattingBehavior = .pad
timer?.setEventHandler { [weak self] in
guard let start = self?.start else { return }
let elapsed = (self?.totalElapsed ?? 0) + CACurrentMediaTime() - start
self?.label.text = formatter.string(from: elapsed)
}
}
var start: CFTimeInterval? // if nil, timer not running
var totalElapsed: CFTimeInterval?
@objc func didTapButton(_ button: UIButton) {
if start == nil {
startTimer()
} else {
pauseTimer()
}
}
private func startTimer() {
start = CACurrentMediaTime()
timer?.resume()
}
private func pauseTimer() {
timer?.suspend()
totalElapsed = (totalElapsed ?? 0) + (CACurrentMediaTime() - start!)
start = nil
}