毎分関数を実行するにはどうすればよいですか? JavaScriptではsetInterval
のようなことができますが、Swiftでも似たようなことがありますか?
欲しい出力:
Hello World、1分に1回...
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
func sayHello()
{
NSLog("hello World")
}
Foundationをインポートすることを忘れないでください。
スウィフト4:
var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)
@objc func sayHello()
{
NSLog("hello World")
}
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()
}
Swift 2では、NSTimer
を作成します。 Swift 2を使用している場合は、10.0より前のiOSバージョンを使用している可能性があります。その場合、古いtarget
/selector
パターンを使用する必要があります。
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()
}
NSTimer
が一般的に最適ですが、完全を期すために、バックグラウンドスレッドでタイマーをスケジュールするのに役立つディスパッチタイマーも使用できることに注意してください。ディスパッチタイマーはブロックベースであるため、target
参照を使用する限り、selector
の古いNSTimer
/weak
パターンによる強力な参照サイクルの課題を回避できます。
したがって、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()
}
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()
}
詳細については、 Dispatch Sources のDispatch Source ExamplesのCreating a Timerセクションを参照してください。 同時実行プログラミングガイドのセクション。
名前付き関数ではなくクロージャを使用したSwift 3(NSTimer
がNSTimer
に名前が変更された)のTimer
回答の更新を次に示します。
var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
(_) in
print("Hello world")
}
NSTimer
を使用できます
var timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)
Selector()に関数名を入れます
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()
これは、特定のキューでディスパッチする必要がある場合に特に便利です。また、これをユーザーインターフェイスの更新に使用することを計画している場合は、GPUのリフレッシュレートと同期しているため、CADisplayLink
を調べることをお勧めします。
ある程度のドリフトを許すできる場合、毎分コードを実行する簡単なソリューションを次に示します。
private func executeRepeatedly() {
// put your code here
DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
self?.executeRepeatedly()
}
}
executeRepeatedly()
を1回実行するだけで、毎分実行されます。所有オブジェクト(self
)が解放されると、実行が停止します。フラグを使用して、実行を停止する必要があることを示すこともできます。