Reputation: 7
I have set up a timer class to firer when the viewDidLoad(). I want to have a timer on multiple view controllers thoughout the app. If you have a better solution to a accurate timer on multiple views please suggest.
Viewcontroller -> One of the views that needs a timer
override func viewDidLoad() {
super.viewDidLoad()
func setupTimer() {
// Setupt the timer, this will call the timerFired method every second
var timer = NSTimer(
timeInterval: 1.0,
target: self,
selector: #selector(TestTimer.timerFired()),//<- Error Code
userInfo: nil,
repeats: true)
}
The Error Code: Use of instance member 'timerFired' on type 'TestTimer',did you mean to use a value of type 'TestTimer' instead?
Timer Class -> Checks start date compared to current date/time for a accurate timer
class TestTimer: NSTimer {
var timer = NSTimer()
// Converter changes String into NSDate
var startDate = converter("Tue, 26 Apr 2016 09:01:00 MDT")
// Function to be fired
func timerFired() {
let now = NSDate()
let difference = now.timeIntervalSinceDate(self.startDate)
// Format the difference for display
// For example, minutes & seconds
let dateComponentsFormatter = NSDateComponentsFormatter()
dateComponentsFormatter.stringFromTimeInterval(difference)
print(difference)
}
}
Upvotes: 0
Views: 209
Reputation: 80781
The error you're getting is pretty obscure. What it's trying to tell you is you should remove the ()
from the end of your timerFired
in the #selector
.
var timer = NSTimer(
timeInterval: 1.0,
target: self,
selector: #selector(TestTimer.timerFired),
userInfo: nil,
repeats: true)
However, this isn't going to make your code how you want it to work – as self
in the timer declaration refers to the view controller, not the timer. I would recommend you create a wrapper class for NSTimer
, along with a delegate pattern in order to achieve what you want.
You should note that the documentation states that you shouldn't attempt to subclass NSTimer
, so you could do something like this instead:
// the protocol that defines the timerDidFire callback method
protocol TimerDelegate:class {
func timerDidFire(cumulativeTime:NSTimeInterval)
}
// your timer wrapper class
class TimerWrapper {
// the underlying timer object
weak private var _timer:NSTimer?
// the start date of when the timer first started
private var _startDate = NSDate()
// the delegate used to implement the timerDidFire callback method
weak var delegate:TimerDelegate?
// start the timer with a given firing interval – which could be a property
func startTimer(interval:NSTimeInterval) {
// if timer already exists, make sure to stop it before starting another one
if _timer != nil {
stopTimer()
}
// reset start date and start new timer
_startDate = NSDate()
_timer = NSTimer.scheduledTimerWithTimeInterval(interval,
target: self,
selector: #selector(timerDidFire),
userInfo: nil, repeats: true)
}
// invalidate & deallocate the timer,
// make sure to call this when you're done with the timer
func stopTimer() {
_timer?.invalidate()
_timer = nil
}
// make sure to stop the timer when the wrapper gets deallocated
deinit {
stopTimer()
}
// called when the timer fires
@objc func timerDidFire() {
// get the change in time, from when the timer first fired to now
let deltaTime = NSDate().timeIntervalSinceDate(_startDate)
// do something with delta time
// invoke the callback method
delegate?.timerDidFire(deltaTime)
}
}
You can then use it like this:
// your view controller class – make sure it conforms to the TimerDelegate
class ViewController: UIViewController, TimerDelegate {
// an instance of the timer wrapper class
let timer = TimerWrapper()
override func viewDidLoad() {
super.viewDidLoad()
// set the timer delegate and start the timer – delegate should be set in viewDidLoad,
// timer can be started whenever you need it to be started.
timer.delegate = self
timer.startTimer(1)
}
func timerDidFire(cumulativeTime: NSTimeInterval) {
// do something with the total time
let dateComponentsFormatter = NSDateComponentsFormatter()
let text = dateComponentsFormatter.stringFromTimeInterval(cumulativeTime)
label.text = text
}
}
As far as the appropriateness of using an NSTimer
here goes, as you're only using a time interval of 1 second, an NSTimer
is suitable. By taking the time interval over the total timer duration, you can average out any small firing inaccuracies.
Upvotes: 1
Reputation: 914
This is how a timer is initialized
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0 , target: self, selector: #selector(TestTimer.timerFired()), userInfo: nil, repeats: true)
Upvotes: 0