在Swift中使用NSTimer

在这种情况下,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) } } 

您可以创build一个计划的计时器,自动将其自身添加到runloop并开始触发:

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

或者,您可以保留当前的代码,并在准备就绪时将计时器添加到runloop:

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

我对卢克使用了类似的方法。 对于那些“私人方法”的人来说,唯一的一个警告是纯粹主义者:

不要在Swift中使callback私有。

如果你写:

 private func timerCallBack(timer: NSTimer){ 

..

你会得到:

timerCallBack:]:无法识别的select器发送到实例…终止应用程序由于未捕获的exception'NSInvalidArgumentException'

除非使用NSTimer.scheduledTimerWithTimeInterval否则NSTimer不会自动计划:

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

正如Drewag和Ryan所指出的那样,您需要创build一个计划的计时器(或者自己计划)。创build计划已经很简单了:

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

你还需要改变你的timerFunc(和相关的select器)的定义来接受一个参数并以':'结尾

 func timerFunc(timer:NSTimer!) { ... } 

运行循环的Swift 3.0语法thingy:

 RunLoop.current.add(myTimer, forMode: .commonModes) 

这是一些代码,演示了如何使用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)实现延迟的函数,以使计时器无效(终止,结束)。 和passend“计时器”你也可以访问userInfo(在那里你可以把任何对象,不仅string对象,以及集合types,如数组和字典)。

原来的苹果文件说“” – >定时器自己作为parameter passing,因此该方法将采用以下模式: – (void)timerFireMethod:(NSTimer *)定时器完全读取 – > 在这里

由于这个线程让我试着把计时器放在RunLoop上(这解决了我的问题),所以我也发布了我的具体情况 – 谁知道它可以帮助别人。 我的计时器是在应用程序启动和所有对象的初始化过程中创build的。 我的问题是,虽然它计划了计时器,它仍然没有开火。 我的猜测是,这是因为scheduledTimerWithTimeInterval在启动应用程序期间将计时器放在不同的RunLoop上。 如果我只是初始化计时器,然后使用NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode) ,它可以正常工作。

要使用OPbuild议的方法来完成,您需要将其添加到运行循环中:

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

文件还说,目标应该有一个参数,但它没有它的工作。

 func timerFireMethod(timer: NSTimer) { } 

对于Swift 3

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

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