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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With