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