Last active
August 19, 2020 14:03
-
-
Save illescasDaniel/1702d3844f683c0680b1e5fb6fb1f006 to your computer and use it in GitHub Desktop.
Swift countdown timer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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