Uso de un NSTimer en Swift


En este escenario, timerFunc() nunca se llama. ¿Qué me estoy perdiendo?

class AppDelegate: NSObject, NSApplicationDelegate {

    var myTimer: NSTimer? = nil

    func timerFunc() {
        println("timerFunc()")
    }

    func applicationDidFinishLaunching(aNotification: NSNotification?) {
        myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
    }
}
Author: RobertJoseph, 2014-06-23

10 answers

Puede crear un temporizador programado que se agrega automáticamente al runloop y comienza a disparar:

NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "timerDidFire:", userInfo: userInfo, repeats: true)

O bien, puede mantener su código actual y agregar el temporizador al runloop cuando esté listo para ello:

let myTimer = NSTimer(timeInterval: 0.5, target: self, selector: "timerDidFire:", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(myTimer, forMode: NSRunLoopCommonModes)
 86
Author: Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-23 15:28:39

Uso un enfoque similar a Lucas. Solo una advertencia para las personas que son puristas de "métodos privados":

NO hacer callback privado en Swift.

Si escribes:

private func timerCallBack(timer: NSTimer){

..

Obtendrá:

TimerCallBack:]: selector no reconocido enviado a la instancia... La terminación de la aplicación debido a uncaught exception 'NSInvalidArgumentException'

 8
Author: ingconti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-07 06:56:56

Los NSTimers no se programan automáticamente a menos que utilice NSTimer.scheduledTimerWithTimeInterval:

myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc", userInfo: nil, repeats: true)
 7
Author: drewag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-23 15:27:19

Como Drewag y Ryan señalaron, necesita crear un temporizador programado (o programarlo usted mismo) Es más fácil crearlo programado ya con:

myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc:", userInfo: nil, repeats: true)

También necesita cambiar su definición de timerFunc (y el selector asociado) para tomar un argumento y terminar con un ':'

func timerFunc(timer:NSTimer!) {
    ...
}
 6
Author: David Berry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-23 15:31:50

Sintaxis Swift 3.0 para el bucle de ejecución:

RunLoop.current.add(myTimer, forMode: .commonModes)
 5
Author: Florin Odagiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-07 17:12:39

Para Swift 3

var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(ViewController.updateTimer), userInfo: nil, repeats: true);
RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)
 5
Author: Chandu kumar.Alasyam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-02 09:49:01

Este es un poco de código, que demuestra cómo llamar a una función (retrasada) con Y sin un parámetro.

Use esto en un nuevo proyecto en xCode (singleViewApplication) y ponga el código en el controlador ViewController estándar:

class ViewController: UIViewController {

    override func viewDidLoad() {

        super.viewDidLoad()

        NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("delayedFunctionWithoutParameter:"), userInfo: nil, repeats: false)

        let myParameter = "ParameterStringOrAnyOtherObject"

        NSTimer.scheduledTimerWithTimeInterval(4.0, target: self, selector: Selector("delayedFunctionWithParameter:"), userInfo: myParameter, repeats: false)
    }

    // SIMPLE TIMER - Delayed Function Call
    func delayedFunctionWithoutParameter(timer : NSTimer) {
        print("This is a simple function beeing called without a parameter passed")
        timer.invalidate()
    }

    // ADVANCED TIMER - Delayed Function Call with a Parameter
    func delayedFunctionWithParameter(timer : NSTimer) {

        // check, wether a valid Object did come over
        if let myUserInfo: AnyObject = timer.userInfo {
            // alternatively, assuming it is a String for sure coming over
            // if let myUserInfo: String = timer.userInfo as? String {
            // assuming it is a string comming over
            print("This is an advanced function beeing called with a parameter (in this case: \(myUserInfo)) passed")
        }

        timer.invalidate()
    }
}

Tenga en cuenta que, en cualquier caso, debe implementar la función retardada con el parámetro (timer : NSTimer) para poder invalidar (terminar, finalizar) el temporizador. Y con el passend "timer" también tiene acceso al userInfo (y allí puede poner cualquier objeto, no solo String-Objects, así como tipos de colección como arrays y diccionarios).

La documentación original de Apple dice "" - > El temporizador se pasa a sí mismo como argumento, por lo que el método adoptaría el siguiente patrón: - (void)timerFireMethod: (NSTimer*) timer Leer completamente -> aquí

 4
Author: LukeSideWalker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-08 15:31:58

Dado que este hilo me hizo intentar poner el temporizador en un RunLoop yo mismo (lo que resolvió mi problema), también publico mi caso específico - quién sabe tal vez ayude a alguien. Mi temporizador se crea durante el inicio de la aplicación y la inicialización de todos los objetos. Mi problema era que, mientras programaba el temporizador, aún no disparaba. Mi conjetura es, este fue el caso porque scheduledTimerWithTimeInterval estaba poniendo el temporizador en un RunLoop diferente durante el inicio de la aplicación. Si solo inicializo el temporizador y luego uso NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode) en cambio, funciona bien.

 3
Author: everSin berserch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-12 21:48:26

Con swift3, se puede ejecutar con,

var timer: Timer?
func startTimer() {

    if timer == nil {
        timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.loop), userInfo: nil, repeats: true)
    }
}

func stopTimer() {
    if timer != nil {
        timer?.invalidate()
        timer = nil
    }
}

func loop() {
    //do something
}
 3
Author: Kris Roofe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-16 06:13:38

Para hacerlo con el método que el OP sugiere, debe agregarlo a un bucle de ejecución:

myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)

La documentación también dice que el objetivo debe tomar un argumento, pero funciona sin él.

func timerFireMethod(timer: NSTimer) { }
 2
Author: Grimxn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-23 15:45:44