Быстрый NSTimer userinfo

Я пытаюсь передать UIButton с пользовательской информацией NSTimer. Я прочитал каждый пост в stackoverflow на NSTimers. Я очень близко, но не могу добраться. Это сообщение помогло

Swift NSTimer извлекает userInfo как CGPoint

func timeToRun(ButonToEnable:UIButton) {
    var  tempButton = ButonToEnable
    timer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: Selector("setRotateToFalse"), userInfo: ["theButton" :tempButton], repeats: false)    
}

функция, выполняемая таймером

func setRotateToFalse() {
    println(  timer.userInfo )// just see whats happening

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

Ответ 1

Я понимаю, что вам удалось это исправить, но я подумал, что дам вам немного больше информации об использовании NSTimer. Правильный способ доступа к объекту таймера и, следовательно, информация пользователя - использовать его, как показано ниже. При инициализации таймера вы можете создать его так:

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)

Затем обратный вызов выглядит следующим образом:

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()    
}

Поэтому вам не нужно сохранять ссылку на таймер и избегать часто неприятных глобальных переменных там, где это возможно. Вы можете столкнуться с проблемой в swift, если ваш класс не наследует от NSObject, где говорится, что нет обратного вызова, но это можно легко устранить, добавив @objc в начале определения функции.

Ответ 2

Я просто собирался опубликовать это, когда я прочитал его, прежде чем я разместил сообщение. Я заметил, что у меня было timer.invalidate() до userinfo, поэтому почему он не работал. Я опубликую его, поскольку это может помочь кому-то еще.

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
}

Ответ 3

macOS 10.12+ и iOS 10.0+ представляет API на основе блоков Timer, что является более удобным способом

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

Таймер с одним выстрелом будет автоматически аннулирован после его срабатывания.


Аналогичным удобным способом для таймера с одним выстрелом является использование GCD (DispatchQueue.main.asyncAfter)

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