Swiftでx分ごとに何かを行う


回答:


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

1
しかし、ビューを切り替えたい場合はどうでしょうか?コードは正しく停止しますか?
Cing

5
@Cingは、自己参照の内容に依存します。
Antzi 2016年

1
NSTimerターゲットを保持することを忘れないでください。したがって、この設定でhelloWorldTimerは、プロパティselfself保持helloWorldTimerhelloWorldTimer保持の保持サイクルになりますself
MANIAK_dobrii

@MANIAK_dobriiまた、保持サイクルを解除する方法についてコメントできますか?VCが却下されてもタイマーがキャンセルされない場合、サイクルはまだ影響を受けていませんか?したがって、タイマーをキャンセルしてから、ビューを閉じてサイクルを壊す必要がありますか?
Dave G

1
Swift 4の場合、セレクターを取得するメソッドをObjective-Cに公開する必要があるため、メソッド宣言に@objc属性を追加する必要があります。例: `` `@objc func sayHello(){}` ``
Shamim Hossain

136

iOSバージョン10以上を対象とする場合は、ブロックベースのレンディションのを使用できますTimer。これにより、強力な参照サイクルの可能性が簡素化されます。例:

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

一方でTimer、一般的に最善である、完全を期すために、私は、バックグラウンドスレッドでタイマーをスケジュールするために有用である、あなたはまた、ディスパッチタイマーを使用することができることに注意してください。ディスパッチタイマーを使用すると、ブロックベースであるため、参照を使用している限り、の古いtarget/ selectorパターンによる強力な参照サイクルの課題のいくつかを回避Timerできweakます。

そう:

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!.schedule(deadline: .now(), repeating: .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については、この回答の以前のリビジョンを参照してください。


このアプローチの中で、1回だけ実行するタイマーをどのように使いますか?
Juan Boero

@JuanPabloBoero-ファイアワンスの状況ではこのアプローチを使用しません。使用しますdispatch_after。または繰り返さないNSTimer
Rob

@Rob関数から毎秒更新されるカウンターラベルが画面にあり、上記のコードを使用してカウンターをインクリメントし、ラベルテキストを更新しています。しかし、私が直面している問題は、カウンター変数が毎秒更新されるが、画面のUILabelに最新のカウンター値が表示されないことです。
Nagendra Rao 2016

Rao、上記はバックグラウンドスレッドで何らかのアクションを実行するのに役立ちます。ただし、UIの更新はメインキューで行う必要があります。したがって、これをメインスレッドでスケジュールするか、少なくともUIの更新をメインスレッドにディスパッチします。
Rob

1
この質問は、この回答へのコメントには含まれていません。上記のコメントを削除して、独自の質問を投稿してください。ただし、簡単に言うと、通常は実際にアプリをバックグラウンドで実行し続けるのではなく、実際の状態に保つだけです。stackoverflow.com/a/31642036/1271826を参照してください。
Rob

17

以下は、名前付き関数ではなくクロージャーを使用するNSTimerSwift 3(NSTimer名前がに変更されたTimer)の回答の更新です。

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
    (_) in
    print("Hello world")
}

6
これはiOS 10専用です。
Glenn

iOS

13

ある程度の時間のずれを許容できる場合は毎分いくつかのコードを実行する簡単なソリューションを次に示します。

private func executeRepeatedly() {
    // put your code here

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
        self?.executeRepeatedly()
    }
}

executeRepeatedly()一度実行するだけで、毎分実行されます。所有オブジェクト(self)が解放されると、実行が停止します。フラグを使用して、実行を停止する必要があることを示すこともできます。


この決定は、これらすべてのタイマーを使用して、それらをrunloopsに追加し、無効化するよりもはるかに便利です。
julia_v

これは有効な解決策のようですが、Webサービス呼び出しで使用すると保持サイクルが作成されます...
jayant rawat

11

使用できますTimer(swift 3)

var timer = Timer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)

selector()に関数名を入れます


Swift 3でそれを行うにはどうすればよいですか?
bibcy 2016年

1
use Timer...のNSTimer名前が変更されました
Joseph

7

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()

これは、特定のキューでディスパッチする必要がある場合に特に役立ちます。また、これをユーザーインターフェイスの更新に使用する予定がある場合はCADisplayLink、GPUリフレッシュレートと同期していることを確認することをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.