Timer.scheduledTimer does not work in Swift 3
I found that creating the timer in an OperationQueue Operation did not work. I assume this is because there is no runloop.
Therefore, the following code fixed my problem:
DispatchQueue.main.async { // timer needs a runloop? self.timeoutTimer = Timer.scheduledTimer(timeInterval: self.timeout, target: self, selector: #selector(self.onTimeout(_:)), userInfo: nil, repeats: false)}
Timer methods with a selector are supposed to have one parameter: The timer itself. Thus your code should really look like this: 1
Timer.scheduledTimer(timeInterval: 1.1, target: self, selector: #selector(self.adjustmentBestSongBpmHeartRate(_:), userInfo: nil, repeats: false)@objc func adjustmentBestSongBpmHeartRate(_ timer: Timer) { print("frr") }
Note that if your app only runs on iOS >= 10, you can use the new method that takes a block to invoke rather than a target/selector. Much cleaner and more type-safe:
class func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer
That code would look like this:
timer = Timer.scheduledTimer(withTimeInterval: 1.1, repeats: false) { timer in //Put the code that be called by the timer here. print("frr") }
Note that if your timer block/closure needs access to instance variables from your class you have to take special care with self
. Here's a good pattern for that sort of code:
timer = Timer.scheduledTimer(withTimeInterval: 1.1, repeats: false) { //"[weak self]" creates a "capture group" for timer [weak self] timer in //Add a guard statement to bail out of the timer code //if the object has been freed. guard let strongSelf = self else { return } //Put the code that be called by the timer here. print(strongSelf.someProperty) strongSelf.someOtherProperty = someValue }
Edit (updated 15 December)
1: I should add that the method you use in the selector has to use Objective-C dynamic dispatch. In Swift 4 and later, the individual methods you reference must be tagged with the @objc
tag. In previous versions of Swift you could also declare the entire class that defines the selector with the @objc
qualifier, or you could make the class that defined the selector a subclass of NSObject
or any class that inherits from NSOBject
. (It's quite common to define the method the timer calls inside a UIViewController
, which is a subclass of NSObject
, so it used to "just work".
Swift 3
In my case it worked after I added to my method the @obj prefix
Class TestClass { private var timer: Timer? func start() { guard timer == nil else { return } timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(handleMyFunction), userInfo: nil, repeats: false) } func stop() { guard timer != nil else { return } timer?.invalidate() timer = nil } @objc func handleMyFunction() { // Code here }}