如何在Swift中使用NSTimer ?

时间:2023-01-22 16:23:07

I tried

我试着

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

But, I got an error saying

但是,我说错了

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

12 个解决方案

#1


480  

This will work:

这将工作:

override func viewDidLoad() {
    super.viewDidLoad()
    //Swift >=3 selector syntax
    var timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
    //Swift 2.2 selector syntax
    var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
    //Swift <2.2 selector syntax
    var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}

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

For Swift 4, the method of which you want to get the selector must be exposed to Objective-C, thus @objc attribute must be added to the method declaration.

对于Swift 4,您想要获取选择器的方法必须暴露在Objective-C中,因此必须将@objc属性添加到方法声明中。

#2


116  

Here are some somewhat fuller examples updated for Swift 3.

以下是为Swift 3更新的一些更完整的示例。

Repeated event

You can use a timer to do an action multiple times, as seen in the following example. The timer calls a method to update a label every half second.

您可以使用计时器多次执行操作,如下面的示例所示。计时器调用一个方法来每隔半秒更新一个标签。

如何在Swift中使用NSTimer ?

Here is the code for that:

这是它的代码:

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

Delayed event

You can also use a timer to schedule a one time event for some time in the future. The main difference from the above example is that you use repeats: false instead of true.

您还可以使用计时器在未来的一段时间内安排一次事件。与上面的例子的主要区别是,您使用重复:false而不是true。

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

The above example calls a method named delayedAction two seconds after the timer is set. It is not repeated, but you can still call timer.invalidate() if you need to cancel the event before it ever happens.

上面的示例在设置计时器两秒后调用名为delayedAction的方法,它不会重复,但是如果需要在事件发生之前取消它,仍然可以调用timer.invalidate()。

Notes

  • If there is any chance of starting your timer instance multiple times, be sure that you invalidate the old timer instance first. Otherwise you lose the reference to the timer and you can't stop it anymore. (see this Q&A)
  • 如果有可能多次启动您的计时器实例,请确保首先使旧的计时器实例无效。否则,您将失去对计时器的引用,并且无法再停止它。(见问答)
  • Don't use timers when they aren't needed. See the timers section of the Energy Efficiency Guide for iOS Apps.
  • 不要在不需要的时候使用计时器。参见iOS应用程序能效指南的定时器部分。

Related

#3


22  

Updated to Swift 4, leveraging userInfo:

更新到Swift 4,利用userInfo:

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

}

#4


20  

As of iOS 10 there is also a new block based Timer factory method which is cleaner than using the selector:

在ios10中,还有一种新的基于块的定时器工厂方法,比使用选择器更简洁:

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

#5


15  

Swift 3, pre iOS 10

Swift 3, ios10

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+

斯威夫特3,iOS 10 +

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

Notes

笔记

  • It needs to be on the main queue
  • 它需要位于主队列上
  • Callback function can be public, private, ...
  • 回调函数可以是public、private、…
  • Callback function needs to be @objc
  • 回调函数需要是@objc

#6


14  

Check with:

检查:

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

#7


8  

You will need to use Timer instead of NSTimer in Swift 3.

在Swift 3中,你需要使用计时器而不是NSTimer。

Here is an example:

这是一个例子:

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
}

#8


6  

for swift 3 and Xcode 8.2 (nice to have blocks, but if You compile for iOS9 AND want userInfo):

对于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)
    }

#9


4  

SimpleTimer (Swift 3.1)

Why?

This is a simple timer class in swift that enables you to:

这是swift中的一个简单的定时器类,使您能够:

  • Local scoped timer
  • 局部作用域的计时器
  • Chainable
  • 证明
  • One liners
  • 一个衬垫
  • Use regular callbacks
  • 使用常规的回调

Usage:

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

Code:

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

#10


2  

In Swift 3 something like this with @objc:

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

#11


2  

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

And Create Fun By The Name createEnemy

创造乐趣的名字创造敌人

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

#12


1  

If you init method of timer

如果你初始化timer的方法

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

func update(_ timer : Timer) {

}

then add it to loop using method other selector will not be called

然后使用不调用其他选择器的方法将其添加到循环中

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

NOTE : If you are want this to repeat make repeats true and keep the reference of timer otherwise update method will not be called.

注意:如果您想让这个重复使repeat为真,并保留timer的引用,否则更新方法将不会被调用。

If you are using this method.

如果你使用这个方法。

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

keep a reference for later use if repeats is true.

如果重复是正确的,为以后使用保留一个参考。

#1


480  

This will work:

这将工作:

override func viewDidLoad() {
    super.viewDidLoad()
    //Swift >=3 selector syntax
    var timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
    //Swift 2.2 selector syntax
    var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
    //Swift <2.2 selector syntax
    var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}

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

For Swift 4, the method of which you want to get the selector must be exposed to Objective-C, thus @objc attribute must be added to the method declaration.

对于Swift 4,您想要获取选择器的方法必须暴露在Objective-C中,因此必须将@objc属性添加到方法声明中。

#2


116  

Here are some somewhat fuller examples updated for Swift 3.

以下是为Swift 3更新的一些更完整的示例。

Repeated event

You can use a timer to do an action multiple times, as seen in the following example. The timer calls a method to update a label every half second.

您可以使用计时器多次执行操作,如下面的示例所示。计时器调用一个方法来每隔半秒更新一个标签。

如何在Swift中使用NSTimer ?

Here is the code for that:

这是它的代码:

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

Delayed event

You can also use a timer to schedule a one time event for some time in the future. The main difference from the above example is that you use repeats: false instead of true.

您还可以使用计时器在未来的一段时间内安排一次事件。与上面的例子的主要区别是,您使用重复:false而不是true。

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

The above example calls a method named delayedAction two seconds after the timer is set. It is not repeated, but you can still call timer.invalidate() if you need to cancel the event before it ever happens.

上面的示例在设置计时器两秒后调用名为delayedAction的方法,它不会重复,但是如果需要在事件发生之前取消它,仍然可以调用timer.invalidate()。

Notes

  • If there is any chance of starting your timer instance multiple times, be sure that you invalidate the old timer instance first. Otherwise you lose the reference to the timer and you can't stop it anymore. (see this Q&A)
  • 如果有可能多次启动您的计时器实例,请确保首先使旧的计时器实例无效。否则,您将失去对计时器的引用,并且无法再停止它。(见问答)
  • Don't use timers when they aren't needed. See the timers section of the Energy Efficiency Guide for iOS Apps.
  • 不要在不需要的时候使用计时器。参见iOS应用程序能效指南的定时器部分。

Related

#3


22  

Updated to Swift 4, leveraging userInfo:

更新到Swift 4,利用userInfo:

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

}

#4


20  

As of iOS 10 there is also a new block based Timer factory method which is cleaner than using the selector:

在ios10中,还有一种新的基于块的定时器工厂方法,比使用选择器更简洁:

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

#5


15  

Swift 3, pre iOS 10

Swift 3, ios10

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+

斯威夫特3,iOS 10 +

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

Notes

笔记

  • It needs to be on the main queue
  • 它需要位于主队列上
  • Callback function can be public, private, ...
  • 回调函数可以是public、private、…
  • Callback function needs to be @objc
  • 回调函数需要是@objc

#6


14  

Check with:

检查:

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

#7


8  

You will need to use Timer instead of NSTimer in Swift 3.

在Swift 3中,你需要使用计时器而不是NSTimer。

Here is an example:

这是一个例子:

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
}

#8


6  

for swift 3 and Xcode 8.2 (nice to have blocks, but if You compile for iOS9 AND want userInfo):

对于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)
    }

#9


4  

SimpleTimer (Swift 3.1)

Why?

This is a simple timer class in swift that enables you to:

这是swift中的一个简单的定时器类,使您能够:

  • Local scoped timer
  • 局部作用域的计时器
  • Chainable
  • 证明
  • One liners
  • 一个衬垫
  • Use regular callbacks
  • 使用常规的回调

Usage:

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

Code:

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

#10


2  

In Swift 3 something like this with @objc:

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

#11


2  

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

And Create Fun By The Name createEnemy

创造乐趣的名字创造敌人

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

#12


1  

If you init method of timer

如果你初始化timer的方法

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

func update(_ timer : Timer) {

}

then add it to loop using method other selector will not be called

然后使用不调用其他选择器的方法将其添加到循环中

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

NOTE : If you are want this to repeat make repeats true and keep the reference of timer otherwise update method will not be called.

注意:如果您想让这个重复使repeat为真,并保留timer的引用,否则更新方法将不会被调用。

If you are using this method.

如果你使用这个方法。

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

keep a reference for later use if repeats is true.

如果重复是正确的,为以后使用保留一个参考。