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