web-dev-qa-db-ja.com

NSTimerをSwiftで使用する

このシナリオでは、timerFunc()は呼び出されません。私は何が欠けていますか?

class AppDelegate: NSObject, NSApplicationDelegate {

    var myTimer: NSTimer? = nil

    func timerFunc() {
        println("timerFunc()")
    }

    func applicationDidFinishLaunching(aNotification: NSNotification?) {
        myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
    }
}
42
RobertJoseph

自身をrunloopに自動的に追加し、起動を開始するスケジュールタイマーを作成できます。

スイフト2

NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "timerDidFire:", userInfo: userInfo, repeats: true)

Swift 3、4、5

Timer.scheduledTimer(withTimeInterval: 0.5, target: self, selector: #selector(timerDidFire(_:)), userInfo: userInfo, repeats: true)

または、現在のコードを保持し、準備ができたら実行ループにタイマーを追加できます。

スイフト2

let myTimer = NSTimer(timeInterval: 0.5, target: self, selector: "timerDidFire:", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(myTimer, forMode: NSRunLoopCommonModes)

Swift 3、4、5

let myTimer = Timer(timeInterval: 0.5, target: self, selector: #selector(timerDidFire(_:)), userInfo: nil, repeats: true)
RunLoop.current.add(myTimer, forMode: RunLoop.Mode.common)
92
Ryan

ルークと同様のアプローチを使用します。 「プライベートメソッド」純粋主義者である人々への唯一の警告:

Swiftではコールバックをプライベートにしないでください。

あなたが書く場合:

private func timerCallBack(timer: NSTimer){

..

あなたが取得します:

timerCallBack:]:認識されないセレクターがインスタンスに送信されました...キャッチされていない例外 'NSInvalidArgumentException'によりアプリを終了しています

8
ingconti

NSTimerは、NSTimer.scheduledTimerWithTimeIntervalを使用しない限り、自動的にスケジュールされません。

myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc", userInfo: nil, repeats: true)
7
drewag

DrewagとRyanが指摘したように、スケジュールタイマーを作成する(または自分でスケジュールする)必要があります。

myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc:", userInfo: nil, repeats: true)

また、timerFunc(および関連するセレクター)の定義を変更して、引数を取り、「:」で終わる必要があります。

func timerFunc(timer:NSTimer!) {
    ...
}
6
David Berry

Swiftの場合

var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(ViewController.updateTimer), userInfo: nil, repeats: true);
RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)

実行ループ用のSwift 3.0構文:

RunLoop.current.add(myTimer, forMode: .commonModes)
5
Florin Odagiu

これは少しのコードであり、パラメーターなしでANDを使用して関数(遅延)を呼び出す方法を示しています。

XCode(singleViewApplication)の新しいプロジェクトでこれを使用し、コードを標準のviewControllerに配置します。

class ViewController: UIViewController {

    override func viewDidLoad() {

        super.viewDidLoad()

        NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("delayedFunctionWithoutParameter:"), userInfo: nil, repeats: false)

        let myParameter = "ParameterStringOrAnyOtherObject"

        NSTimer.scheduledTimerWithTimeInterval(4.0, target: self, selector: Selector("delayedFunctionWithParameter:"), userInfo: myParameter, repeats: false)
    }

    // SIMPLE TIMER - Delayed Function Call
    func delayedFunctionWithoutParameter(timer : NSTimer) {
        print("This is a simple function beeing called without a parameter passed")
        timer.invalidate()
    }

    // ADVANCED TIMER - Delayed Function Call with a Parameter
    func delayedFunctionWithParameter(timer : NSTimer) {

        // check, wether a valid Object did come over
        if let myUserInfo: AnyObject = timer.userInfo {
            // alternatively, assuming it is a String for sure coming over
            // if let myUserInfo: String = timer.userInfo as? String {
            // assuming it is a string comming over
            print("This is an advanced function beeing called with a parameter (in this case: \(myUserInfo)) passed")
        }

        timer.invalidate()
    }
}

いずれにしても、タイマーを無効化(終了、終了)できるように、パラメーター(timer:NSTimer)で遅延関数を実装する必要があることに注意してください。また、パスエンド「タイマー」を使用すると、userInfoにもアクセスできます(そして、String-Objectだけでなく、配列や辞書などのコレクションタイプだけでなく、任意のObjectを配置できます)。

Appleの元のドキュメントには、「」->タイマーが引数として渡されるため、メソッドは次のパターンを採用します。 void)timerFireMethod:(NSTimer *)timer Read full-> ---(here

4
LukeSideWalker

このスレッドを使用して、自分でRunLoopにタイマーを設定しようとしたため(問題が解決しました)、特定のケースも投稿しました。私のタイマーは、アプリの起動時およびすべてのオブジェクトの初期化時に作成されます。私の問題は、タイマーをスケジュールしている間、それがまだ起動しなかったことでした。私の推測では、これはscheduledTimerWithTimeIntervalがアプリの起動中に別のRunLoopにタイマーを置いていたためです。タイマーを初期化してからNSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)を代わりに使用すると、正常に機能します。

3

Swift3を使用すると、それを実行できます。

var timer: Timer?
func startTimer() {

    if timer == nil {
        timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.loop), userInfo: nil, repeats: true)
    }
}

func stopTimer() {
    if timer != nil {
        timer?.invalidate()
        timer = nil
    }
}

func loop() {
    //do something
}
3
Kris Roofe

OPが提案する方法でそれを行うには、実行ループに追加する必要があります。

myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)

ドキュメントには、ターゲットが引数を取るべきであると書かれていますが、ターゲットがなくても動作します。

func timerFireMethod(timer: NSTimer) { }
2
Grimxn