Faites quelque chose toutes les X minutes dans Swift

Comment puis-je exécuter une fonction Toutes les minutes? En JavaScript, je peux faire quelque chose comme setInterval, quelque chose de similaire existe-t-il dans Swift?

Sortie souhaitée:

Bonjour le monde une fois par minute...

83
demandé sur Arashsoft 2014-09-20 22:24:42

6 réponses

var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)

func sayHello() 
{
    NSLog("hello World")
}

N'oubliez pas d'importer Foundation.

Swift 4:

 var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)

 @objc func sayHello() 
 {
     NSLog("hello World")
 }
137
répondu Unheilig 2018-08-15 23:27:14

Dans Swift 3, vous pouvez créer un Timer. Et si vous ciblez iOS version 10 et supérieure, vous pouvez utiliser le rendu basé sur des blocs, ce qui simplifie les cycles de référence forts potentiels, par exemple:

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

Dans Swift 2, vous créez un NSTimer. Et si vous utilisez Swift 2, il se peut que vous utilisiez la version iOS antérieure à 10.0, auquel cas vous devez utiliser l'ancienne target/selector motif:

weak var timer: NSTimer?

func startTimer() {
    timer?.invalidate()   // just in case you had existing `NSTimer`, `invalidate` it before we lose our reference to it
    timer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true)
}

func handleTimer(timer: NSTimer) {
    // do something here
}

func stopTimer() {
    timer?.invalidate()
}

// because this old target/selector approach will keep a strong reference
// to the `target`, if you want the timer to stop when the view controller
// is dismissed, you can't stop the timer in `deinit`, but rather have to 
// detect the dismissing of the view controller using other mechanisms. Commonly,
// we used to detect the view disappearing, like below:

override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    stopTimer()
}

Alors que NSTimer est généralement le meilleur, par souci d'exhaustivité, je dois noter que vous pouvez utilisez également dispatch timer, ce qui est utile pour la planification des minuteries sur les threads d'arrière-plan. Avec les temporisateurs de répartition, puisqu'ils sont basés sur des blocs, cela évite certains des défis de cycle de référence forts avec l'ancien target/selector modèle de NSTimer, tant que vous utilisez des références weak.

Donc, dans Swift 3:

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!.scheduleRepeating(deadline: .now(), interval: .seconds(60))
    timer!.setEventHandler { [weak self] in
        // do whatever you want here
    }
    timer!.resume()
}

func stopTimer() {
    timer?.cancel()
    timer = nil
}

deinit {
    self.stopTimer()
}

Dans Swift 2:

var timer: dispatch_source_t?

func startTimer() {
    let queue = dispatch_queue_create("com.domain.app.timer", nil) // again, you can use `dispatch_get_main_queue()` if you want to use the main queue
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
    dispatch_source_set_timer(timer!, DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC, 1 * NSEC_PER_SEC) // every 60 seconds, with leeway of 1 second
    dispatch_source_set_event_handler(timer!) { [weak self] in
        // do whatever you want here
    }
    dispatch_resume(timer!)
}

func stopTimer() {
    if let timer = timer {
        dispatch_source_cancel(timer)
        self.timer = nil
    }
}

deinit {
    self.stopTimer()
}

Pour plus d'informations, reportez-vous à la sectioncréation D'une minuterie de exemples de source de répartition dans la répartition Sources section du guide de programmation de concurrence .

113
répondu Rob 2017-10-12 06:31:26

Voici une mise à jour de la réponse NSTimer, pour Swift 3 (dans laquelle NSTimer a été renommé en Timer) en utilisant une fermeture plutôt qu'une fonction nommée:

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
    (_) in
    print("Hello world")
}
14
répondu John T 2016-12-03 00:37:09

Vous pouvez utiliser NSTimer

var timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)

Dans selector () vous mettez dans votre nom de fonction

10
répondu Bas 2014-09-20 18:30:39

Dans swift 3.0, le GCD a été refactorisé:

let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)

timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
    NSLog("Hello World")
}
timer.resume()

Ceci est particulièrement utile lorsque vous devez envoyer sur une file d'attente particulière. En outre, si vous prévoyez d'utiliser ceci pour la mise à jour de l'interface utilisateur, je suggère de regarder dans CADisplayLink car il est synchronisé avec le taux de rafraîchissement du GPU.

7
répondu Can 2016-11-30 20:58:41

Si vous pouvez permettre une certaine dérive de temps Voici une solution simple exécutant du code toutes les minutes:

private func executeRepeatedly() {
    // put your code here

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
        self?.executeRepeatedly()
    }
}

Exécutez simplement executeRepeatedly() Une fois et il sera exécuté toutes les minutes. L'exécution s'arrête lorsque l'objet propriétaire (self) est libéré. Vous pouvez également utiliser un indicateur pour indiquer que l'exécution doit s'arrêter.

2
répondu algrid 2018-03-02 17:42:39