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'
12 answers
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.
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.
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
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)
}
}
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
}
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
Verifique com:
var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true);
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
}
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)
}
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()
}
}
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()
}
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 ////
}
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.