swift NSTimer userinfo swift NSTimer userinfo swift swift

swift NSTimer userinfo


I realise you've managed to fix this but I thought I would give you a little more information about using NSTimer. The correct way to access the timer object and hence user info is to use it like below. When initialising the timer you can create it like this:

Swift 2.x

NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: Selector("setRotateToFalse:"), userInfo: ["theButton" :tempButton], repeats: false)

Swift 3.x<

Timer.scheduledTimer(timeInterval: 1, target: self, selector:#selector(ViewController.setRotateToFalse), userInfo: ["theButton" :tempButton], repeats: false)

Then the callback looks like this:

func setRotateToFalse(timer:NSTimer) {    rotate = false    let userInfo = timer.userInfo as Dictionary<String, AnyObject>    var tempbutton:UIButton = (userInfo["theButton"] as UIButton)    tempbutton.enabled = true    timer.invalidate()    }

Therefore you don't need to keep a reference to the timer and avoid often nasty global variables where possible. You may run into an issue in swift if your class doesn't inherit from NSObject where it says there is no callback defined but this can be easily fixed by adding @objc at the beginning of the function definition.


I was just going to post this as I read over it before I posted. I noticed that I had timer.invalidate() before userinfo so that's why it wasn't working. I will post it as it may help somebody else.

func setRotateToFalse(timer:NSTimer) {    rotate = false    timer.invalidate()    let userInfo = timer.userInfo as Dictionary<String, AnyObject>    var tempbutton:UIButton = (userInfo["theButton"] as UIButton)    tempbutton.enabled = true}


macOS 10.12+ and iOS 10.0+ introduces a block based API of Timer which is a more convenient way

func timeToRun(buttonToEnable: UIButton) {    timer = Timer.scheduledTimer(withTimeInterval:4, repeats: false) { timer in         buttonToEnable.enabled = true    }    }

A one shot timer will be invalidated automatically after it fires.


An similar convenient way for a one shot timer is using GCD (DispatchQueue.main.asyncAfter)

func timeToRun(buttonToEnable: UIButton) {    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4)) {        buttonToEnable.enabled = true    }}