2017-10-17 24 views
0

Je souhaite arrêter cette minuterie, puis la redémarrer depuis l'endroit où je l'ai arrêtée.Arrêter et redémarrer une minuterie

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

Ci-dessous, il a été suggéré que je ne devrais pas incrémenter un compteur dans mon gestionnaire de minuterie. Pourquoi pas?

Par exemple, en utilisant la minuterie 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() 
} 

Répondre

0

Nous ne mettre en pause/reprendre Timer instances. Nous les arrêtons avec invalidate(). Et quand vous voulez le redémarrer, créez simplement une nouvelle minuterie.

Veuillez vous reporter à the Timer documentation, également disponible dans Xcode.


Notez que vous pouvez suspend et resume minuteries 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 
} 

S'il vous plaît noter que je ne veux pas dire que si vous voulez suspend et resume que vous devez utiliser GCD DispatchSourceTimer. Appeler invalidate et recréer Timer comme nécessaire est assez simple, alors faites-le. Je fournis uniquement ces informations GCD par souci d'exhaustivité. Par ailleurs, en règle générale, ne jamais "incrémenter" certains compteurs dans votre gestionnaire de minuterie. C'est une erreur de débutant commun. Les chronomètres ne sont pas garantis pour tirer à chaque fois ou avec une précision exacte. Toujours enregistrer une heure de référence au début, puis dans votre gestionnaire d'événements, calculer les différences entre l'heure actuelle et l'heure de début. Par exemple, étendre mon exemple de minuteur 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

Et comment puis-je créer un compteur de secondes où je peux l'arrêter et le reprendre? Merci beaucoup –

+0

Capturez l'heure de début ('CACurrentMediaTime()' ou 'CFAbsoluteTimeGetCurrent()') lorsque vous démarrez une minuterie et lorsque vous mettez en pause le minuteur, calculez le temps écoulé entre 'CACurrentMediaTime()' ou 'CFAbsoluteTimeGetCurrent()' et le heure de début enregistrée. – Rob

+0

Je ne comprends pas pouvez-vous m'aider avec le code? –