简体   繁体   English

如何在 Swift 中使用 Timer(以前称为 NSTimer)?

[英]How can I use Timer (formerly NSTimer) in Swift?

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'

This will work:这将起作用:

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
}

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属性添加到方法声明中。

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.计时器每半秒调用一个方法来更新一个标签。

在此处输入图片说明

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 .与上述示例的主要区别在于您使用repeats: 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.上面的示例在设置计时器两秒后调用名为delayedAction的方法。 It is not repeated, but you can still call timer.invalidate() if you need to cancel the event before it ever happens.它不会重复,但如果您需要在事件发生之前取消它,您仍然可以调用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有关的

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

}

As of iOS 10 there is also a new block based Timer factory method which is cleaner than using the selector:从 iOS 10 开始,还有一个新的基于块的 Timer 工厂方法,它比使用选择器更简洁:

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

Swift 3, pre iOS 10 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+斯威夫特 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, ...回调函数可以是公共的、私有的、......
  • Callback function needs to be @objc回调函数需要是@objc

Check with:检查:

Swift 2斯威夫特 2

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

Swift 3, 4, 5斯威夫特 3、4、5

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

Swift 5斯威夫特 5

I personally prefer the Timer with the block closure:我个人更喜欢带有块关闭的计时器:

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

You will need to use Timer instead of NSTimer in Swift 3.您将需要在 Swift 3 中使用Timer而不是 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
}

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

First declare your timer首先声明你的计时器

var timer: Timer?

Then add line in viewDidLoad() or in any function you want to start the timer然后在 viewDidLoad() 或要启动计时器的任何函数中添加行

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

This is the func you will callback it to do something it must be @objc这是您将回调它以执行某些操作的函数,它必须是@objc

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

SimpleTimer (Swift 3.1) 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()
    }
}
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

And Create Fun By The Name createEnemy并以名字创造乐趣 createEnemy

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

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

If you init method of 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.注意:如果您希望此重复,则 make 重复 true 并保留计时器的引用,否则将不会调用更新方法。

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.如果重复为真,请保留参考以备后用。

I tried to do in a NSObject Class and this worked for me:我试图在 NSObject 类中做,这对我有用:

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

NSTimer has been renamed to Timer in Swift 4.2. NSTimer 已在 Swift 4.2 中重命名为 Timer。 this syntax will work in 4.2:此语法适用于 4.2:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM