Como posso usar o NSTimer no Swift?

eu tentei

var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)
Mas, tenho um erro a dizer:
'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
Author: rmaddy, 2014-06-03

12 answers

Isto vai funcionar.
override func viewDidLoad() {
    super.viewDidLoad()
    // Swift block syntax (iOS 10+)
    let timer = Timer(timeInterval: 0.4, repeats: true) { _ in print("Done!") }
    // Swift >=3 selector syntax
    let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
    // Swift 2.2 selector syntax
    let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
    // Swift <2.2 selector syntax
    let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}

// must be internal or public. 
@objc func update() {
    // Something cool
}

Para o Swift 4, o método do qual você quer obter o selector deve ser exposto ao Objective-C, assim @objc atributo deve ser adicionado à declaração do método.

 494
Author: Oscar Swanros, 2018-07-16 17:50:08

Aqui estão alguns exemplos um pouco mais completos actualizados para Swift 3.

Acontecimento repetido

Pode usar um temporizador para fazer uma acção várias vezes, como se vê no exemplo seguinte. O temporizador chama um método para atualizar uma etiqueta a cada meio segundo.

enter image description here

Aqui está o código para isso:

import UIKit

class ViewController: UIViewController {

    var counter = 0
    var timer = Timer()

    @IBOutlet weak var label: UILabel!

    // start timer
    @IBAction func startTimerButtonTapped(sender: UIButton) {
        timer.invalidate() // just in case this button is tapped multiple times

        // start the timer
        timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
    }

    // stop timer
    @IBAction func cancelTimerButtonTapped(sender: UIButton) {
        timer.invalidate()
    }

    // called every time interval from the timer
    func timerAction() {
        counter += 1
        label.text = "\(counter)"
    }
}

Acontecimento retardado

Você também pode usar um temporizador para agendar um evento de uma vez para algum tempo no futuro. A principal diferença em relação ao acima exemplo é que você usa repeats: false em vez de true.

timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)

O exemplo acima chama um método chamado delayedAction dois segundos após o temporizador estar definido. Não é repetido, mas você ainda pode chamar timer.invalidate() Se você precisar cancelar o evento antes que isso aconteça.

Notas

  • Se houver alguma hipótese de iniciar a instância do seu temporizador várias vezes, certifique-se que invalida a instância do velhote primeiro. Caso contrário, perde-se a referência ao temporizador e já não se pode pará-lo. (ver Este Q & A)
  • Não use Temporizadores quando não são necessários. Ver a secção timers do Guia de eficiência energética para aplicações iOS .

Relacionado

 125
Author: Suragch, 2018-10-07 06:48:42

Actualizado para Swift 4, alavancando userInfo:

class TimerSample {

    var timer: Timer?

    func startTimer() {
        timer = Timer.scheduledTimer(timeInterval: 5.0,
                                     target: self,
                                     selector: #selector(eventWith(timer:)),
                                     userInfo: [ "foo" : "bar" ],
                                     repeats: true)
    }

    // Timer expects @objc selector
    @objc func eventWith(timer: Timer!) {
        let info = timer.userInfo as Any
        print(info)
    }

}
 24
Author: igraczech, 2018-02-16 14:17:20

A partir de iOS 10 existe também um novo método de fábrica de Temporizadores baseados em blocos que é mais limpo do que usar o selector:

    _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
        label.isHidden = true
    }
 21
Author: Josh Homann, 2016-10-21 19:16:39

Swift 3, pre iOS 10

func schedule() {
    DispatchQueue.main.async {
      self.timer = Timer.scheduledTimer(timeInterval: 20, target: self,
                                   selector: #selector(self.timerDidFire(timer:)), userInfo: nil, repeats: false)
    }
  }

  @objc private func timerDidFire(timer: Timer) {
    print(timer)
  }

Swift 3, iOS 10+

DispatchQueue.main.async {
      self.timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: false) { timer in
        print(timer)
      }
    }

Notas

  • tem de estar na fila principal
  • A função de Callback pode ser pública, privada ...
  • a função de Callback tem de ser @objc
 16
Author: onmyway133, 2017-02-16 11:50:10

Verifique com:

var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true);
 14
Author: Midhun MP, 2014-12-23 05:46:25

Terá de usar O temporizador em vez do NSTimer no Swift 3.

Aqui está um exemplo:

Timer.scheduledTimer(timeInterval: 1, 
    target: self, 
    selector: #selector(YourController.update), 
    userInfo: nil, 
    repeats: true)

// @objc selector expected for Timer
@objc func update() {
    // do what should happen when timer triggers an event
}
 10
Author: Ondrej Kvasnovsky, 2018-02-19 01:19:37

Para swift 3 e Xcode 8.2 (é bom ter blocos, mas se você compilar para o iOS9 e quer userInfo):

...

        self.timer = Timer(fireAt: fire,
                           interval: deltaT,
                           target: self,
                           selector: #selector(timerCallBack(timer:)),
                           userInfo: ["custom":"data"],
                           repeats: true)

        RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
        self.timer!.fire()
}

func timerCallBack(timer: Timer!){
        let info = timer.userInfo
        print(info)
    }
 6
Author: ingconti, 2016-12-30 13:57:41

SimpleTimer (Swift 3.1)

Porquê? Esta é uma classe de temporizadores simples no swift que lhe permite:
  • temporizador local scoped
  • Chainable
  • uma linha
  • usar callbacks regulares

Utilização:

SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs

Código:

class SimpleTimer {/*<--was named Timer, but since swift 3, NSTimer is now Timer*/
    typealias Tick = ()->Void
    var timer:Timer?
    var interval:TimeInterval /*in seconds*/
    var repeats:Bool
    var tick:Tick

    init( interval:TimeInterval, repeats:Bool = false, onTick:@escaping Tick){
        self.interval = interval
        self.repeats = repeats
        self.tick = onTick
    }
    func start(){
        timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(update), userInfo: nil, repeats: true)//swift 3 upgrade
    }
    func stop(){
        if(timer != nil){timer!.invalidate()}
    }
    /**
     * This method must be in the public or scope
     */
    @objc func update() {
        tick()
    }
}
 4
Author: eonist, 2017-10-11 19:21:55

In Swift 3 algo assim com @objc:

func startTimerForResendingCode() {
    let timerIntervalForResendingCode = TimeInterval(60)
    Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
                         target: self,
                         selector: #selector(timerEndedUp),
                         userInfo: nil,
                         repeats: false)
}




@objc func timerEndedUp() {
    output?.timerHasFinishedAndCodeMayBeResended()
}
 2
Author: Nik Kov, 2017-07-31 22:24:31
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
E criar diversão com o nome createEnemy
fund createEnemy ()
{
do anything ////
}
 2
Author: Khaled Hamdy, 2017-10-07 01:20:01

Se utilizar o método do temporizador

let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)

func update(_ timer : Timer) {

}

Depois adiciona - o ao ciclo usando o método outro selector não será chamado

RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)

Nota: Se quiser que isto repita, faça repetições verdadeiras e mantenha a referência do temporizador, caso contrário, o método de actualização não será chamado.

Se está a utilizar este método.

Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)

Manter uma referência para utilização posterior se as repetições forem verdadeiras.

 1
Author: commando24, 2017-05-10 06:51:06