How can I run a function every minute?In JavaScript I can do something like setInterval
, does something similar exist in Swift?
我怎样才能每分钟运行一个函数?在JavaScript中我可以做类似setInterval的事情,在Swift中是否存在类似的东西?
Wanted output:
Hello World once a minute...
你好世界每分钟一次......
6 个解决方案
#1
137
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)func sayHello() { NSLog("hello World")}
Remember to import Foundation.
记得导入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") }
#2
113
In Swift 3, you can create a Timer
. And if targeting iOS version 10 and greater, you can use the block-based rendition, which simplifies the potential strong reference cycles, e.g.:
在Swift 3中,您可以创建一个Timer。如果针对iOS 10及更高版本,您可以使用基于块的再现,这简化了潜在的强引用周期,例如:
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()}
In Swift 2, you create a NSTimer
. And if you're using Swift 2, you may well be using iOS version prior to 10.0, in which case you have to use the older target
/selector
pattern:
在Swift 2中,您创建了一个NSTimer。如果你使用的是Swift 2,你很可能会使用10.0之前的iOS版本,在这种情况下你必须使用旧的目标/选择器模式:
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()}
While NSTimer
is generally best, for the sake of completeness, I should note that you can also use dispatch timer, which is useful for scheduling timers on background threads. With dispatch timers, since they're block-based, it avoids some of the strong reference cycle challenges with the old target
/selector
pattern of NSTimer
, as long as you use weak
references.
虽然NSTimer通常是最好的,但为了完整起见,我应该注意你也可以使用dispatch timer,这对于在后台线程上调度定时器很有用。使用调度计时器,因为它们是基于块的,所以只要您使用弱引用,它就可以避免使用NSTimer的旧目标/选择器模式的一些强大的参考周期挑战。
So, in Swift 3:
所以,在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()}
In Swift 2:
在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()}
For more information, see the the Creating a Timer section of Dispatch Source Examples in the Dispatch Sources section of the Concurrency Programming Guide.
有关更多信息,请参阅“并发编程指南”的“Dispatch Sources”部分中的“Dispatch Source Examples”的“Creating a Timer”部分。
#3
14
Here's an update to the NSTimer
answer, for Swift 3 (in which NSTimer
was renamed to Timer
) using a closure rather than a named function:
这是对使用闭包而不是命名函数的Swift 3(其中NSTimer被重命名为Timer)的NSTimer答案的更新:
var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { (_) in print("Hello world")}
#4
11
You can use NSTimer
您可以使用NSTimer
var timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)
In selector() you put in your function name
在selector()中输入你的函数名
#5
7
In swift 3.0 the GCD got refactored:
在swift 3.0中,GCD被重构:
let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))timer.setEventHandler{ NSLog("Hello World")}timer.resume()
This is specially useful for when you need to dispatch on a particular Queue. Also, if you're planning on using this for user interface updating, I suggest looking into CADisplayLink
as it's synchronized with the GPU refresh rate.
当您需要在特定队列上调度时,这特别有用。此外,如果您计划将其用于用户界面更新,我建议您查看CADisplayLink,因为它与GPU刷新率同步。
#6
2
If you can allow for some time drift here's a simple solution executing some code every minute:
如果你可以允许一段时间漂移,这是一个简单的解决方案,每分钟执行一些代码:
private func executeRepeatedly() { // put your code here DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in self?.executeRepeatedly() }}
Just run executeRepeatedly()
once and it'll be executed every minute. The execution stops when the owning object (self
) is released. You also can use a flag to indicate that the execution must stop.
只需运行executeRepeatedly()一次,它就会每分钟执行一次。释放拥有对象(self)时执行停止。您还可以使用标志来指示执行必须停止。
#1
137
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)func sayHello() { NSLog("hello World")}
Remember to import Foundation.
记得导入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") }
#2
113
In Swift 3, you can create a Timer
. And if targeting iOS version 10 and greater, you can use the block-based rendition, which simplifies the potential strong reference cycles, e.g.:
在Swift 3中,您可以创建一个Timer。如果针对iOS 10及更高版本,您可以使用基于块的再现,这简化了潜在的强引用周期,例如:
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()}
In Swift 2, you create a NSTimer
. And if you're using Swift 2, you may well be using iOS version prior to 10.0, in which case you have to use the older target
/selector
pattern:
在Swift 2中,您创建了一个NSTimer。如果你使用的是Swift 2,你很可能会使用10.0之前的iOS版本,在这种情况下你必须使用旧的目标/选择器模式:
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()}
While NSTimer
is generally best, for the sake of completeness, I should note that you can also use dispatch timer, which is useful for scheduling timers on background threads. With dispatch timers, since they're block-based, it avoids some of the strong reference cycle challenges with the old target
/selector
pattern of NSTimer
, as long as you use weak
references.
虽然NSTimer通常是最好的,但为了完整起见,我应该注意你也可以使用dispatch timer,这对于在后台线程上调度定时器很有用。使用调度计时器,因为它们是基于块的,所以只要您使用弱引用,它就可以避免使用NSTimer的旧目标/选择器模式的一些强大的参考周期挑战。
So, in Swift 3:
所以,在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()}
In Swift 2:
在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()}
For more information, see the the Creating a Timer section of Dispatch Source Examples in the Dispatch Sources section of the Concurrency Programming Guide.
有关更多信息,请参阅“并发编程指南”的“Dispatch Sources”部分中的“Dispatch Source Examples”的“Creating a Timer”部分。
#3
14
Here's an update to the NSTimer
answer, for Swift 3 (in which NSTimer
was renamed to Timer
) using a closure rather than a named function:
这是对使用闭包而不是命名函数的Swift 3(其中NSTimer被重命名为Timer)的NSTimer答案的更新:
var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { (_) in print("Hello world")}
#4
11
You can use NSTimer
您可以使用NSTimer
var timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)
In selector() you put in your function name
在selector()中输入你的函数名
#5
7
In swift 3.0 the GCD got refactored:
在swift 3.0中,GCD被重构:
let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))timer.setEventHandler{ NSLog("Hello World")}timer.resume()
This is specially useful for when you need to dispatch on a particular Queue. Also, if you're planning on using this for user interface updating, I suggest looking into CADisplayLink
as it's synchronized with the GPU refresh rate.
当您需要在特定队列上调度时,这特别有用。此外,如果您计划将其用于用户界面更新,我建议您查看CADisplayLink,因为它与GPU刷新率同步。
#6
2
If you can allow for some time drift here's a simple solution executing some code every minute:
如果你可以允许一段时间漂移,这是一个简单的解决方案,每分钟执行一些代码:
private func executeRepeatedly() { // put your code here DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in self?.executeRepeatedly() }}
Just run executeRepeatedly()
once and it'll be executed every minute. The execution stops when the owning object (self
) is released. You also can use a flag to indicate that the execution must stop.
只需运行executeRepeatedly()一次,它就会每分钟执行一次。释放拥有对象(self)时执行停止。您还可以使用标志来指示执行必须停止。