Daniel K
Daniel K

Reputation: 1129

NSTimer is not firing when called in a block

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?

Upvotes: 10

Views: 4574

Answers (1)

AdamM
AdamM

Reputation: 4440

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

Upvotes: 33

Related Questions