Question or problem in the Swift programming language:
I have a Swift class that I’d like to look something like this:
class UpdateManager { let timer: NSTimer init() { timer = NSTimer(timeInterval: 600, target: self, selector: "check", userInfo: nil, repeats: true) } func check() { // Do some stuff } }
However, Swift doesn’t like the fact that I’m passing self to the NSTimer initializer. Am I breaking some pattern here? How is one supposed to accomplish initialization like this?
How to solve the problem:
Solution 1:
You’ve found the primary use case of the Implicitly Unwrapped Optional.
- You need to access
self
frominit
, beforetimer
is initialized. - Otherwise,
timer
should never be nil, so you shouldn’t have to check it outside ofinit
.
So, you should declare let timer: NSTimer!
.
Solution 2:
It’s possible that Swift 2 has changed what works. I’m using code like the following:
@objc class Test : NSObject { var timer : NSTimer! init text() { super.init() timer = NSTimer(timeInterval: 1.0, target: self, selector: "timerFired:", userInfo: nil, repeats: true) NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) } }
Needed both @objc declaration and NSObject subclass.
Also timer needs to be a var, not let.
Solution 3:
Aside from the implicitly unwrapped optional, I found that to get the code working I needed to subclass NSObject and to also add the timer to current run loop.
class UpdateManager:NSObject { let timer: NSTimer! override init() { super.init() timer = NSTimer(timeInterval: 600, target: self, selector: "check", userInfo: nil, repeats: true) NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode) } func check() { // Do some stuff } }
Updated code based on comments – thank you to jtbandes and Caroline
class UpdateManager { let timer: NSTimer! init() { timer = NSTimer.scheduledTimerWithTimeInterval(600, target: self, selector: "check", userInfo: nil, repeats: true) } @objc func check() { // Do some stuff } }