Skip to content

Instantly share code, notes, and snippets.

@illescasDaniel
Last active August 19, 2020 14:03
Show Gist options
  • Select an option

  • Save illescasDaniel/1702d3844f683c0680b1e5fb6fb1f006 to your computer and use it in GitHub Desktop.

Select an option

Save illescasDaniel/1702d3844f683c0680b1e5fb6fb1f006 to your computer and use it in GitHub Desktop.
Swift countdown timer
// MIT License
import Foundation
class CountdownTimer {
struct ClockTime {
let hours: Int
let minutes: Int
let seconds: Int
let milliseconds: Int
static var zero: ClockTime {
ClockTime(hours: 0, minutes: 0, seconds: 0, milliseconds: 0)
}
}
enum State {
case started
case progress(clockTime: ClockTime, timeRemaining: TimeInterval)
case finished
}
private var timer: Timer?
private let timeIntervalInFuture: TimeInterval
private let countDownInterval: TimeInterval
private let timerTolerance: TimeInterval
init(timeIntervalInFuture: TimeInterval, countDownInterval: TimeInterval, timerTolerance: TimeInterval = 0) {
self.timeIntervalInFuture = timeIntervalInFuture
self.countDownInterval = countDownInterval
self.timerTolerance = timerTolerance
}
func start(completionHandler: @escaping (State) -> Void) {
completionHandler(.started)
let startTime = Date().timeIntervalSince1970
timer = Timer.scheduledTimer(withTimeInterval: countDownInterval, repeats: true) { (timer) in
let endTime = startTime + self.timeIntervalInFuture
let timeRemainingInSeconds = endTime - Date().timeIntervalSince1970
if timeRemainingInSeconds <= 0 {
completionHandler(.progress(clockTime: .zero, timeRemaining: timeRemainingInSeconds))
completionHandler(.finished)
timer.invalidate()
self.timer = nil
} else {
let hoursRounded = Int(timeRemainingInSeconds.rounded()) / 3600
let minutesRounded = Int(timeRemainingInSeconds.rounded()) / 60
let secondsRounded = Int(timeRemainingInSeconds.rounded()) % 60
let milliseconds = ( (timeRemainingInSeconds - floor(timeRemainingInSeconds)) * 1000 ).rounded()
let millisecondsRounded = Int(milliseconds)
completionHandler(.progress(clockTime: ClockTime(hours: hoursRounded, minutes: minutesRounded, seconds: secondsRounded, milliseconds: millisecondsRounded), timeRemaining: timeRemainingInSeconds))
}
}
timer?.tolerance = timerTolerance
}
func stop() {
self.timer?.invalidate()
self.timer = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment