Swiftでタイマー(旧NSTimer)を使用するにはどうすればよいですか?


257

私は試した

var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)

しかし、私は言ってエラーを得ました

'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'

1
「SwiftでNSTimerを使用するにはどうすればよいですか?」– Objective-Cで使用するのと同じ方法。そのAPIは変更されていません。
常磁性クロワッサン2015

回答:


535

これは動作します:

override func viewDidLoad() {
    super.viewDidLoad()
    // Swift block syntax (iOS 10+)
    let timer = Timer(timeInterval: 0.4, repeats: true) { _ in print("Done!") }
    // Swift >=3 selector syntax
    let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
    // Swift 2.2 selector syntax
    let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
    // Swift <2.2 selector syntax
    let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}

// must be internal or public. 
@objc func update() {
    // Something cool
}

Swift 4の場合、セレクターを取得するメソッドをObjective-Cに公開する@objc必要があるため、メソッド宣言に属性を追加する必要があります。


2
これらのメソッドを含むクラスはNSObjectである必要があることを追加します。そうしないと、認識されないセレクターエラーが発生します
Joshua

27
Xcode 6.1以降、「@ objc func update(){」のように「@objc」を関数ヘッダーに追加する必要がありました。それがなければ、アプリは最初の火災でクラッシュします。
kev 2014年

Varタイマーを宣言できます:NSTimer!最初は必要なときにそれを使用してください!
ニジラン

1
ブロック構文のおそらくより便利なバージョン:let timer = Timer.scheduledTimer(withTimeInterval:timeout、repeats:false){_ in print( "Done。")}
Teo Sartori

'let timer = Timer(timeInterval:0.4、repeats:true){_ in print( "Done!")}'は使用できません。これによりタイマーが開始されず、繰り返しを取得できなくなります。Timer.scheduledTimerを使用する必要があります。
Siamaster

149

繰り返しイベント

次の例に示すように、タイマーを使用して複数回アクションを実行できます。タイマーは0.5秒ごとにラベルを更新するメソッドを呼び出します。

ここに画像の説明を入力してください

そのためのコードは次のとおりです。

import UIKit

class ViewController: UIViewController {

    var counter = 0
    var timer = Timer()

    @IBOutlet weak var label: UILabel!

    // start timer
    @IBAction func startTimerButtonTapped(sender: UIButton) {
        timer.invalidate() // just in case this button is tapped multiple times

        // start the timer
        timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
    }

    // stop timer
    @IBAction func cancelTimerButtonTapped(sender: UIButton) {
        timer.invalidate()
    }

    // called every time interval from the timer
    func timerAction() {
        counter += 1
        label.text = "\(counter)"
    }
}

遅延したイベント

タイマーを使用して、将来の1回限りのイベントをスケジュールすることもできます。上記の例との主な違いは、のrepeats: false代わりにを使用することですtrue

timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)

上記の例ではdelayedAction、タイマーが設定されてから2秒後にメソッドを呼び出します。繰り返されませんがtimer.invalidate()、イベントが発生する前にキャンセルする必要がある場合は、引き続き呼び出すことができます。

ノート

  • タイマーインスタンスを複数回起動する可能性がある場合は、必ず最初に古いタイマーインスタンスを無効にしてください。そうしないと、タイマーへの参照が失われ、停止できなくなります。(このQ&Aを参照)
  • 不要なタイマーは使用しないでください。iOSアプリのエネルギー効率ガイドのタイマーセクションをご覧ください。

関連した


1
@raddevus、私に知らせてくれてありがとう。古いSwift 3コメントを削除しました。
Suragch 2018

31

userInfoを利用してSwift 4に更新:

class TimerSample {

    var timer: Timer?

    func startTimer() {
        timer = Timer.scheduledTimer(timeInterval: 5.0,
                                     target: self,
                                     selector: #selector(eventWith(timer:)),
                                     userInfo: [ "foo" : "bar" ],
                                     repeats: true)
    }

    // Timer expects @objc selector
    @objc func eventWith(timer: Timer!) {
        let info = timer.userInfo as Any
        print(info)
    }

}

2
実際の例を示します。関数がNSTimerオブジェクトを
想定

1
それは本当に重要ではありません。必要なものはすべてuserInfo辞書に自由に格納できます。この場合は、任意のキーと値のペアです。
イグラツェッチ2017年

これは便利ですが、Swift 3で機能しなくなった例です。Timer.scheduledTimer(timeInterval:1.0、target:self、selector:#selector(event)、userInfo: "Info Sent"、repeats:true)
Bobby

28

iOS 10以降では、セレクターを使用するよりもクリーンな新しいブロックベースのタイマーファクトリメソッドもあります。

    _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
        label.isHidden = true
    }

1
あなたがそれをやっている方法では、単にを削除して_ = 、単にで始める方がいいのではないでしょうTimerか?
ハニー、

2
未使用の値に関する警告を消す場合、または警告を気にしない場合は、_ =を省略できます。警告付きのコードをチェックインしたくありません。
Josh Homann 2017

22

Swift 3、iOS 10より前

func schedule() {
    DispatchQueue.main.async {
      self.timer = Timer.scheduledTimer(timeInterval: 20, target: self,
                                   selector: #selector(self.timerDidFire(timer:)), userInfo: nil, repeats: false)
    }
  }

  @objc private func timerDidFire(timer: Timer) {
    print(timer)
  }

Swift 3、iOS 10以降

DispatchQueue.main.async {
      self.timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: false) { timer in
        print(timer)
      }
    }

ノート

  • メインキューにある必要があります
  • コールバック関数はパブリック、プライベート、...
  • コールバック関数は @objc

1
私の理解は、タイマーコールバックのみがメインキューにある必要があり、次の方がわずかに効率的であるということです。self.timer = Timer.scheduledTimer(withTimeInterval:20、repeats:false){timer in DispatchQueue.main.async {print (タイマー)}}
Mathieu Frenette 2017

私のタイマーは私のオブジェクトの1つからトリガーしていなかったので、トリックを作りました:)
レイモンドヒル

@ReimondHill変更する必要がありますtimeInterval
onmyway133 '

17

確認する:

スウィフト2

var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true)

スウィフト3、4、5

var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)

2
私はすでに試しましたが、「指定された引数を受け入れる「init」のオーバーロードが見つかりませんでした」と書かれています
user3225917

1
ここでも同じですが、「指定された引数を受け入れる「init」のオーバーロードが見つかりませんでした」というエラーが発生しました。このラインは本当に機能しますか?
Yangshun Tay

@yangshunと同じエラーが発生します。どのタイプのオブジェクトでなければなりませselfんか?UIViewは大丈夫ですか?
SimplGy 2014年

@SimpleAsCouldBe:はい、大丈夫です
Midhun MP 2014年

func amountSubmitSuccess(){self.view.hideToastActivity()self.view.makeToast(message: "The Amount Successfully Registered")var timer = NSTimer.scheduledTimerWithTimeInterval(0.5、target:self、selector: "moveToBidderPage"、userInfo:nil、 repeats:false)} func moveToBidderPage(){let loginPageView = self.storyboard?.instantiateViewControllerWithIdentifier( "bidderpageID")as!BidderPage self.navigationController?.pushViewController(loginPageView、animated:true)}
AG

11

Swift 3ではNSTimerの代わりにTimerを使用する必要があります。

次に例を示します。

Timer.scheduledTimer(timeInterval: 1, 
    target: self, 
    selector: #selector(YourController.update), 
    userInfo: nil, 
    repeats: true)

// @objc selector expected for Timer
@objc func update() {
    // do what should happen when timer triggers an event
}

11

スウィフト5

私は個人的にはブロッククロージャー付きのタイマーを好みます。

    Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
       // TODO: - whatever you want
    }

これはmacOS 10.12以降でのみ利用可能です。iOSについてはわかりません。
jeff-h

iOSでも利用できます。
Wissa

7

Swift 3およびXcode 8.2(ブロックがあると便利ですが、iOS9用にコンパイルしていて、userInfoが必要な場合):

...

        self.timer = Timer(fireAt: fire,
                           interval: deltaT,
                           target: self,
                           selector: #selector(timerCallBack(timer:)),
                           userInfo: ["custom":"data"],
                           repeats: true)

        RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
        self.timer!.fire()
}

func timerCallBack(timer: Timer!){
        let info = timer.userInfo
        print(info)
    }

6

SimpleTimer(Swift 3.1)

どうして?

これはSwiftのシンプルなタイマークラスで、次のことが可能です。

  • ローカルスコープタイマー
  • 連鎖可能
  • ワンライナー
  • 通常のコールバックを使用する

使用法:

SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs

コード:

class SimpleTimer {/*<--was named Timer, but since swift 3, NSTimer is now Timer*/
    typealias Tick = ()->Void
    var timer:Timer?
    var interval:TimeInterval /*in seconds*/
    var repeats:Bool
    var tick:Tick

    init( interval:TimeInterval, repeats:Bool = false, onTick:@escaping Tick){
        self.interval = interval
        self.repeats = repeats
        self.tick = onTick
    }
    func start(){
        timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(update), userInfo: nil, repeats: true)//swift 3 upgrade
    }
    func stop(){
        if(timer != nil){timer!.invalidate()}
    }
    /**
     * This method must be in the public or scope
     */
    @objc func update() {
        tick()
    }
}

次に、いくつかの条件でそのブロック内のタイマーを停止する方法は?
モバイルデベロッパーiOS Android

タイマーへの参照をクラスに格納し、stopを呼び出すだけです。xcodeコンパイラは、エスケープなどが必要かどうかを通知します
eonist

3
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

そして、createEnemyという名前で楽しみを作ります

fund createEnemy ()
{
do anything ////
}

3

最初にタイマーを宣言します

var timer: Timer?

次に、viewDidLoad()またはタイマーを開始する任意の関数に行を追加します

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)

これは、@ objcでなければならないことを実行するためにコールバックする関数です

@objc func action () {
print("done")
}

2

スウィフト3 @objcと、このような何か:

func startTimerForResendingCode() {
    let timerIntervalForResendingCode = TimeInterval(60)
    Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
                         target: self,
                         selector: #selector(timerEndedUp),
                         userInfo: nil,
                         repeats: false)
}




@objc func timerEndedUp() {
    output?.timerHasFinishedAndCodeMayBeResended()
}

1

タイマーのメソッドを初期化した場合

let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)

func update(_ timer : Timer) {

}

次に、メソッドを使用してループに追加します。他のセレクタは呼び出されません

RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)

注:これを繰り返す場合は、繰り返しをtrueにしてタイマーの参照を維持してください。そうしないと、更新メソッドが呼び出されません。

この方法を使用している場合。

Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)

repeatsがtrueの場合、後で使用するために参照を保持します。


0

私はNSObjectクラスでやろうとしましたが、これは私のために働きました:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {  
print("Bang!") }

-2

NSTimerはSwift 4.2でTimerに名前が変更されました。この構文は4.2で機能します。

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)

名前の変更はSwift 3で行われ、他の回答ではすでに更新が行われています...
Eric Aya
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.