2017-10-17 246 views
0

我想停止此计时器,然后从停止它的位置重新启动计时器。停止并重新启动计时器

secondsTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(addSeconds), userInfo: nil, repeats: true) 

下面,有人建议我不应该增加在我的定时器处理程序定时器。为什么不?

例如,使用GCD定时器:

func countSeconds() { 

    secondsTimer = DispatchSource.makeTimerSource(queue: .main) 
    secondsTimer?.schedule(deadline: .now(), repeating: 1.0) 

    secondsTimer?.setEventHandler { [weak self] in 

     self?.addSeconds() 
    } 
} 

@objc func addSeconds() { 
    seconds += 1       
} 

func startGame() { 
    secondsTimer?.resume() 
} 

回答

0

我们不暂停/恢复Timer实例。我们用invalidate()来阻止他们。而当你想重新启动时,只需创建新的定时器。

请参阅the Timer documentation,也可在Xcode中使用。


注意,您可以suspendresume GCD定时器,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 
} 

请注意,我不是建议,如果你想suspendresume,你应该使用GCD DispatchSourceTimer。根据需要调用invalidate并重新创建Timer非常简单,所以请执行此操作。为了完整起见,我仅提供此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 
} 
+0

而我该如何创建一个可以停止和恢复的秒计数器?非常感谢 –

+0

当你启动一个定时器并暂停计时器时,捕获开始时间('CACurrentMediaTime()'或'CFAbsoluteTimeGetCurrent()'),计算'CACurrentMediaTime()'或'CFAbsoluteTimeGetCurrent()'与节省了开始时间。 – Rob

+0

我不明白你能帮我用代码吗? –