2017-10-17 31 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()でそれらを止める。そして、それを再起動したいときは、単に新しいタイマーを作成してください。

Xcodeのthe Timer documentationもご参照ください。


なお、することができます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

コードを教えてもらえませんか? –

関連する問題