Respuestas:
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
func sayHello()
{
NSLog("hello World")
}
Recuerde importar Foundation.
Rápido 4:
var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)
@objc func sayHello()
{
NSLog("hello World")
}
NSTimer
retiene su objetivo, por lo que, con esta configuración, si helloWorldTimer
es una propiedad self
, tiene un ciclo de retención, donde self
retiene helloWorldTimer
y helloWorldTimer
retiene self
.
Si tiene como objetivo la versión 10 de iOS y superior, puede usar la interpretación basada en bloques de Timer
, que simplifica los posibles ciclos de referencia fuertes, por ejemplo:
weak var timer: Timer?
func startTimer() {
timer?.invalidate() // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
// do something here
}
}
func stopTimer() {
timer?.invalidate()
}
// if appropriate, make sure to stop your timer in `deinit`
deinit {
stopTimer()
}
Si bien en Timer
general es lo mejor, en aras de la integridad, debo señalar que también puede usar el temporizador de envío, que es útil para programar temporizadores en subprocesos en segundo plano. Con los temporizadores de despacho, dado que están basados en bloques, evita algunos de los fuertes desafíos del ciclo de referencia con el antiguo target
/ selector
patrón de Timer
, siempre y cuando useweak
referencias.
Entonces:
var timer: DispatchSourceTimer?
func startTimer() {
let queue = DispatchQueue(label: "com.domain.app.timer") // you can also use `DispatchQueue.main`, if you want
timer = DispatchSource.makeTimerSource(queue: queue)
timer!.schedule(deadline: .now(), repeating: .seconds(60))
timer!.setEventHandler { [weak self] in
// do whatever you want here
}
timer!.resume()
}
func stopTimer() {
timer?.cancel()
timer = nil
}
deinit {
self.stopTimer()
}
Para obtener más información, consulte la sección Creación de un temporizador de Ejemplos de fuentes de despacho en la sección Fuentes de despacho de la Guía de programación de simultaneidad.
Para Swift 2, consulte la revisión anterior de esta respuesta .
dispatch_after
. O un no repetitivo NSTimer
.
Aquí hay una actualización de la NSTimer
respuesta, para Swift 3 (en el que NSTimer
se cambió el nombre a Timer
) usando un cierre en lugar de una función con nombre:
var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
(_) in
print("Hello world")
}
Si puede permitir un cierto tiempo de deriva, aquí hay una solución simple que ejecuta un código cada minuto:
private func executeRepeatedly() {
// put your code here
DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
self?.executeRepeatedly()
}
}
Ejecútelo executeRepeatedly()
una vez y se ejecutará cada minuto. La ejecución se detiene cuando self
se libera el objeto propietario ( ). También puede usar una bandera para indicar que la ejecución debe detenerse.
En Swift 3.0, el GCD se refactorizó:
let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
NSLog("Hello World")
}
timer.resume()
Esto es especialmente útil para cuando necesita enviar en una Cola en particular. Además, si planea usar esto para la actualización de la interfaz de usuario, le sugiero que investigue CADisplayLink
ya que está sincronizado con la frecuencia de actualización de la GPU.