如何在Swift中使用NSTimer?

时间:2014-06-03 05:09:02

标签: ios nstimer nstimeinterval swift

我试过

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'

15 个答案:

答案 0 :(得分:510)

这将有效:

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

答案 1 :(得分:137)

重复事件

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

enter image description here

以下是代码:

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

延迟事件

您还可以使用计时器在将来的某个时间安排一次性事件。与上述示例的主要区别在于您使用的是repeats: false而不是true

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

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

注释

  • 如果有可能多次启动计时器实例,请确保先使旧计时器实例无效。否则你将丢失对计时器的引用,你不能再停止它。 (见this Q&A
  • 当他们不需要时,不要使用计时器。请参阅Energy Efficiency Guide for iOS Apps
  • 的计时器部分

相关

答案 2 :(得分:28)

更新到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)
    }

}

答案 3 :(得分:23)

从iOS 10开始,还有一个新的基于块的Timer工厂方法,比使用选择器更简洁:

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

答案 4 :(得分:19)

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

答案 5 :(得分:14)

检查:

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

答案 6 :(得分:10)

您需要在Swift 3中使用Timer而不是NSTimer。

以下是一个例子:

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
}

答案 7 :(得分:9)

快速5

我个人更喜欢带有封闭块的Timer:

String values;

void draw()
{
    while ( myPort.available() > 0) { 
        values = myPort.readStringUntil(lf);
    }

    background(0);
    if (values != null)
    {
        noFill();
        stroke(255, 0, 0);
        strokeWeight(1);
        float end = map(float(values), 735, 4160, 0, height); // 735 is lowest value from sensor and 4160 is max. value from sensor
        fill(255, 0, 0);
        ellipse(200, end, 10, 10);
        line(200, 400, 200, end);
    }
}

答案 8 :(得分:6)

用于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 :(得分:2)

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

答案 10 :(得分:2)

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

通过名称createEnemy创建乐趣

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

答案 11 :(得分:1)

如果你使用init方法

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)

注意:如果你想要重复使重复为真并保留定时器的引用,否则不会调用更新方法。

如果您使用此方法。

Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)
如果重复为真,

保留一个参考供以后使用。

答案 12 :(得分:1)

首先声明您的计时器

var timer: Timer?

然后在viewDidLoad()或您要启动计时器的任何函数中添加行

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

这是函数,您将回调它以执行必须为@objc的操作

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

答案 13 :(得分:0)

我尝试在NSObject类中进行操作,这对我有用:

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

答案 14 :(得分:-1)

NSTimer在Swift 4.2中已重命名为Timer。 此语法将在4.2中工作:

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