'How to make a timer in iOS Swift in a separate class?
I've built a CountdownTimer which i would like to refactor into a separate class so i can reuse it in the MainViewController. How would i go about doing that?
This is my code:
var startTime = NSTimeInterval()
var time:Double = 4
var timer = NSTimer()
/* Outlets */
@IBOutlet weak var timerLabel: UILabel!
/* CountdownTimer function */
func updateTime() {
var currentTime = NSDate.timeIntervalSinceReferenceDate()
var elapsedTime = currentTime - startTime
var seconds = time - elapsedTime
if seconds > 0 {
elapsedTime -= NSTimeInterval(seconds)
timerLabel.text = "\(Int(seconds))"
} else {
timer.invalidate()
timerLabel.fadeOut()
}
}
func startTimer () {
if !timer.valid {
let aSelector : Selector = "updateTime"
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: aSelector, userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate()
}
}
Solution 1:[1]
swift 4 version of tbaranes's answer:
class MyTimer: NSObject {
var startTime: TimeInterval! = TimeInterval()
var time: Double! = 4
var timer: Timer! = Timer()
var timerEndedCallback: (() -> Void)!
var timerInProgressCallback: ((_ elapsedTime: Double) -> Void)!
func startTimer(timerEnded: @escaping () -> Void, timerInProgress: ((_ elapsedTime: Double) -> Void)!) {
if !timer.isValid {
let aSelector : Selector = #selector(MyTimer.updateTime)
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: aSelector, userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate
timerEndedCallback = timerEnded
timerInProgressCallback = timerInProgress
}
}
@objc func updateTime() {
var currentTime = NSDate.timeIntervalSinceReferenceDate
var elapsedTime = currentTime - startTime
var seconds = time - elapsedTime
if seconds > 0 {
elapsedTime -= TimeInterval(seconds)
timerInProgressCallback(elapsedTime)
} else {
timer.invalidate()
timerEndedCallback()
}
}
}
Solution 2:[2]
Based on @tbaranes's answer and because the edit queue is full, here's an updated version that works on SWIFT 5 with some tweaks
protocol CountdownTimerProtocol {
func stopCountdown()
func startCountdown(totalTime: Int, timerEnded: @escaping () -> Void, timerInProgress: @escaping (Int) -> Void)
}
class CountdownTimer: NSObject, CountdownTimerProtocol {
private var timer: Timer?
private var timeRemaining = 0
var timerEndedCallback: (() -> Void)?
var timerInProgressCallback: ((Int) -> Void)?
deinit {
stopCountdown()
}
func stopCountdown() {
timer?.invalidate()
}
func startCountdown(totalTime: Int, timerEnded: @escaping () -> Void, timerInProgress: @escaping (Int) -> Void) {
timeRemaining = totalTime
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(step), userInfo: nil, repeats: true)
timerEndedCallback = timerEnded
timerInProgressCallback = timerInProgress
}
@objc func step() {
if timeRemaining > 0 {
timeRemaining -= 1
timerInProgressCallback?(timeRemaining)
} else {
stopCountdown()
timerEndedCallback?()
}
}
}
How to call it, totalTime is measured in seconds, also remember to invalidate() the timer on deinit {} of this class ??
CountdownTimer().startCountdown(
totalTime: 30,
timerEnded: {
print("Countdown is over")
}, timerInProgress: { elapsedTime in
print(elapsedTime)
}
)
Solution 3:[3]
To use your countdownTimer in a separate class, create a new class and implement the class in your MainViewController and then access the methods.
Alternatively just make your functions global.
Solution 4:[4]
XCode->File->New->Source->Cocoa Touch Class extends from NSObject
import UIKit
class TimerTest: NSObject {
var myTimer:NSTimer?
override init() {
super.init()
print("init worked")
myTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerFuncTriggered:", userInfo: nil, repeats: true)
}
func timerFuncTriggered(timer:NSTimer) {
print("timer started")
}
}
you can use your timer class anytime like:
let myTimer = TimerTest()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Paul Lehn |
| Solution 2 | Javier Heisecke |
| Solution 3 | Wraithseeker |
| Solution 4 | Özgür Ersil |
