最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

[已解决]swift中timer NSTimer.scheduledTimerWithTimeInterval不工作

Swift crifan 4088浏览 0评论

[背景]

swift中,仿照之前的用法去写了个timer:

    func startWsKeepConnectTimer() {
        print("startWsKeepConnectTimer")
        self.wsKeepConnectCounter = self.wsKeepConnectInterval
       
        self.wsKeepConnectTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector:Selector("updateWsKeepConnectCounter"), userInfo: nil, repeats: true)
    }
   
    func updateWsKeepConnectCounter() {
        print("updateWsKeepConnectCounter self.wsKeepConnectCounter=\(self.wsKeepConnectCounter)")
        self.wsKeepConnectCounter -= 1
       
        if self.wsKeepConnectCounter <= 0 {
            self.wsKeepConnectCounter = self.wsKeepConnectInterval
           
            websocketKeepConnect()
        }
    }

结果不工作:

后续的updateWsKeepConnectCounter没有执行到。

[解决过程]

1.以为是当前viewcontroller的问题,所以换为:

//        self.wsKeepConnectTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector:Selector("updateWsKeepConnectCounter"), userInfo: nil, repeats: true)
        self.wsKeepConnectTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: SingletonMainVC(), selector:Selector("updateWsKeepConnectCounter"), userInfo: nil, repeats: true)

还是不行。

2.搜:

swift timer not firing

参考:

Using an NSTimer in Swift – Stack Overflow

ios – NSTimer not working Swift – Stack Overflow

3.搜:

swift scheduledTimerWithTimeInterval not firing

参考:

NSTimer.scheduledTimerWithTimeInterval in Swift Playground – Stack Overflow

加上fire试试:

self.wsKeepConnectTimer.fire()

但是要说明的是:

之前用这个NSTimer.scheduledTimerWithTimeInterval,都不需要手动调用fire就可以自动工作的。

结果fire只使得:

updateWsKeepConnectCounter

运行了一次,就停止了。。

NSTimer Not working swift | Apple Developer Forums

把整个timer的代码都放到另外一个viewcontroller:MainViewController中,结果也还是不工作。。。

swift scheduledtimerwithtimeinterval not working

4.突然发现:

难道是因为:

之前可以正常工作的timer,当时调用NSTimer.scheduledTimerWithTimeInterval是出于UI的主线程-》主线程有Loop

而此处调用的NSTimer.scheduledTimerWithTimeInterval时,是http的的callback-》不是住处主线程,没有Loop的环境,所以就没有效果?

此处去改为:

    func startWsKeepConnectTimer() {
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            print("startWsKeepConnectTimer")
            self.wsKeepConnectCounter = self.wsKeepConnectInterval
           
            self.wsKeepConnectTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector:Selector("updateWsKeepConnectCounter"), userInfo: nil, repeats: true)
            //        self.wsKeepConnectTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: SingletonMainVC(), selector:Selector("updateWsKeepConnectCounter"), userInfo: nil, repeats: true)
           
            //        self.wsKeepConnectTimer.fire()
        })
    }

看看效果。

果然可以了:

[总结]

当使用NSTimer.scheduledTimerWithTimeInterval时,要确保:

1.当前处于有Loop的环境

一般来说,当前的UI主界面就是可以的。

所以,如果不是处于主界面时,则去使用:

    func startWsKeepConnectTimer() {
        //Note: makesure when call NSTimer.scheduledTimerWithTimeInterval, need in Loop environment
        //so here need in main queue
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            print("startWsKeepConnectTimer in main queue")
            self.wsKeepConnectTimer = NSTimer.scheduledTimerWithTimeInterval(
                NSTimeInterval(WebsocketKeepConnectIntervalInSec),
                target: self,
                selector:Selector("websocketKeepConnect"),
                userInfo: nil,
                repeats: true)
        })
    }

即可。

2.要确保计时器的目标接收者始终是有效的

即:

使用NSTimer.scheduledTimerWithTimeInterval时的target参数时

此处一般设置为self,即当前的ViewController

但是要确保此处的当前的ViewController是有效的

一些特殊情况比如:

当前处于Login的登录界面时使用的NSTimer.scheduledTimerWithTimeInterval,传递的self时Login的ViewController

结果登录完成,跳转到其他页面时,而销毁了登录界面

然后就会导致计时器下次调用时,找不到接受者而出错

转载请注明:在路上 » [已解决]swift中timer NSTimer.scheduledTimerWithTimeInterval不工作

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
84 queries in 0.187 seconds, using 22.27MB memory