Comment utiliser NSTimer dans Swift?

j'ai essayé

var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)

mais, j'ai eu une erreur disant

'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
214
demandé sur rmaddy 2014-06-03 09:09:02

12 réponses

Cela va fonctionner:

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
}

pour Swift 4, la méthode dont vous voulez obtenir le sélecteur doit être exposée à L'Objectif-C, donc l'attribut @objc doit être ajouté à la déclaration de méthode.

494
répondu Oscar Swanros 2018-07-16 17:50:08

voici quelques exemples plus complets mis à jour pour Swift 3 .

événement répété

vous pouvez utiliser un timer pour faire une action plusieurs fois, comme vu dans l'exemple suivant. La minuterie appelle une méthode pour mettre à jour l'étiquette de chaque demi-seconde.

enter image description here

voici le code pour cela:

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

événement différé

Vous pouvez également utiliser une minuterie pour programmer un événement unique pour un certain temps dans l'avenir. La principale différence par rapport à l'exemple ci-dessus est que vous utilisez repeats: false au lieu de true .

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

L'exemple ci-dessus appelle une méthode nommée delayedAction deux secondes après que la minuterie est réglée. Il n'est pas répété, mais vous pouvez toujours appeler timer.invalidate() si vous devez annuler l'événement avant qu'il ne se produise.

Notes

  • S'il y a une chance de démarrer votre instance de minuterie plusieurs fois, assurez-vous que vous invalidez d'abord l'instance de l'ancienne minuterie. Sinon, vous perdez la référence au minuteur et vous ne pouvez plus l'arrêter. (voir cette Q&R )
  • N'utilisez pas de minuteries lorsqu'elles ne sont pas nécessaires. Voir la section "minuteries" du Guide D'efficacité énergétique pour les Applications iOS .

Related

125
répondu Suragch 2018-10-07 06:48:42

mis à jour à Swift 4, tirant parti de l'information utilisateur:

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
répondu igraczech 2018-02-16 14:17:20

à partir de iOS 10, Il existe également une nouvelle méthode de fabrication de Minuteries par blocs qui est plus propre que l'utilisation du sélecteur:

    _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
        label.isHidden = true
    }
21
répondu 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)
      }
    }

Notes

  • Il doit être sur la file d'attente principale
  • La fonction de rappel
  • peut être publique, privée, ...
  • fonction de Rappel doit être @objc
16
répondu onmyway133 2017-02-16 11:50:10

consultez:

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

vous devrez utiliser Timer au lieu de NSTimer dans Swift 3.

voici un exemple:

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
répondu Ondrej Kvasnovsky 2018-02-19 01:19:37

pour swift 3 et Xcode 8.2 (c'est bien d'avoir des blocs, mais si vous compilez pour iOS9 et que vous voulez 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
répondu ingconti 2016-12-30 13:57:41

SimpleTimer (Swift 3.1)

pourquoi?

il s'agit d'une classe de minuterie simple dans swift qui vous permet de:

  • Local de l'étendue de la minuterie
  • Chaînage
  • one liners
  • Utiliser les callbacks

Utilisation:

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

Code:

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
répondu eonist 2017-10-11 19:21:55

dans Swift 3 quelque chose comme ça avec @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
répondu Nik Kov 2017-07-31 22:24:31
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

et créer du plaisir par le nom createEnemy

fund createEnemy ()
{
do anything ////
}
2
répondu Khaled Hamdy 2017-10-07 01:20:01

Si vous méthode init de la minuterie

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

func update(_ timer : Timer) {

}

puis l'ajouter à la boucle en utilisant la méthode autre sélecteur ne sera pas appelé

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

NOTE: Si vous voulez que cela se répète, faites les répétitions true et gardez la référence du timer sinon la méthode update ne sera pas appelée.

Si vous utilisez cette méthode.

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

conserver une référence pour une utilisation ultérieure si la répétition est vraie.

1
répondu commando24 2017-05-10 06:51:06