Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTimer is not firing when called in a block

Tags:

swift

nstimer

This works

 func startTimer () {
    batchTimer = NSTimer.scheduledTimerWithTimeInterval(batchIntervalSeconds, target: self, selector: #selector(Requester.performRemoteRequests), userInfo: nil, repeats: false)

}

This doesn't

func startTimerInBlock () {
    let urlRequest = NSMutableURLRequest(URL: NSURL(string: "google.com")!, cachePolicy: .ReloadIgnoringLocalCacheData , timeoutInterval: 30)
    urlRequest.HTTPMethod = "GET"
    let session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration())
    let task = session.dataTaskWithRequest(urlRequest) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
        //check there is a response and that it is an http response
        self.batchTimer = NSTimer.scheduledTimerWithTimeInterval(self.batchIntervalSeconds, target: self, selector: #selector(CNVRRequester.performRemoteRequests), userInfo: nil, repeats: false)

    }
    task.resume()
}

Does anybody know why a timer called within a block does not fire?

like image 846
Daniel Kanaan Avatar asked Apr 20 '16 15:04

Daniel Kanaan


1 Answers

Simple fix, place the self.startTimer code inside a dispatch_block

 DispatchQueue.main.async {
        self.startTimer()
 }

That should fix it.

Edit for explanation

Timers require an active run loop. When you initialize it on main thread, will automatically use main run loop. If you want to run it from a background thread, then you have to attach it to that threads run loop. Example

DispatchQueue.global(qos: .background).async {
    let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: selector(fireTimer), repeats: false)
    let runLoop = RunLoop.current
    runLoop.add(timer, forMode: .defaultRunLoopMode)
    runLoop.run()
  }

However, if you want to make sure it just runs from the main thread, just start it from a dispatch main closure and it will ensure it will run the main thread.

Edit: Updated for Swift 3

Edit 2: Updated to show background timer answer in line with Phil Mitchells comment

like image 147
AdamM Avatar answered Nov 20 '22 22:11

AdamM