I am trying to call a function after a delay. On iOS10 I am able to use Timer.scheduledTimer which does indeed call my closure after the given delay. However, on iOS9 I am using DispatchQueue.main.asyncAfter and it calls my closure with a six second delay.
The delay I am testing with is 60 seconds. Timer.scheduledTimer calls closure after 60 seconds, DispatchQueue.main.asyncAfter after 66 seconds. The six second delay is consequent, if I schedule two delays of 60 seconds the second delay is called after 132 seconds using DispatchQueue.main.asyncAfter.
func delay(delay:Double, closure:@escaping ()->()) {
NSLog("Calling method with delay of: \(delay)")
if #available(iOS 10.0, *) {
Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { (timer) in
closure()
}
} else {
// TODO: Is not accurate, delay of +- 6 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
}
The code that calls the delay function:
func scheduleStudy(minutes: Int, secondsFromNow: Int) {
// Study notification
if #available(iOS 10.0, *) {
self.addiOS10StudyNotification(minutes: minutes, secondsFromNow: secondsFromNow)
}else{
self.addiOS9StudyNotification(minutes: minutes, secondsFromNow: secondsFromNow)
}
// Study timer
delay(delay: Double(secondsFromNow)) {
self.onStudy(minutes: minutes)
}
NSLog("Scheduled study for \(minutes) minutes in \(secondsFromNow) seconds from now.")
}
Planning notifications and methods calls using Timer.scheduledTimer
2016-12-06 13:34:06.024714 Mattie[1386:360881] Calling method with delay of: 0.0
2016-12-06 13:34:06.025072 Mattie[1386:360881] Scheduled study for 1 minutes in 0 seconds from now.
2016-12-06 13:34:06.036953 Mattie[1386:360881] Calling method with delay of: 60.0
2016-12-06 13:34:06.037191 Mattie[1386:360881] Scheduled pause for 1 minutes in 60 seconds from now.
2016-12-06 13:34:06.052520 Mattie[1386:360881] Calling method with delay of: 120.0
2016-12-06 13:34:06.053162 Mattie[1386:360881] Scheduled study for 1 minutes in 120 seconds from now.
2016-12-06 13:34:06.066838 Mattie[1386:360881] Calling method with delay of: 180.0
2016-12-06 13:34:06.067027 Mattie[1386:360881] Scheduled finish in 180 seconds from now.
Pause is called:
2016-12-06 13:35:06.038307 Mattie[1386:360881] ON PAUSE
2016-12-06 13:35:06.065389 Mattie[1386:360881] Added pause timer for 1 minutes
Planned in at 13:34:06, called at 13:35:06
Planning notifications and methods calls using DispatchQueue.main.asyncAfter
2016-12-06 13:36:48.845838 Mattie[1390:361681] Calling method with delay of: 0.0
2016-12-06 13:36:48.847389 Mattie[1390:361681] Scheduled study for 1 minutes in 0 seconds from now.
2016-12-06 13:36:48.854336 Mattie[1390:361681] Calling method with delay of: 60.0
2016-12-06 13:36:48.854543 Mattie[1390:361681] Scheduled pause for 1 minutes in 60 seconds from now.
2016-12-06 13:36:48.861424 Mattie[1390:361681] Calling method with delay of: 120.0
2016-12-06 13:36:48.861601 Mattie[1390:361681] Scheduled study for 1 minutes in 120 seconds from now.
2016-12-06 13:36:48.868464 Mattie[1390:361681] Calling method with delay of: 180.0
2016-12-06 13:36:48.868644 Mattie[1390:361681] Scheduled finish in 180 seconds from now.
Pause is called:
2016-12-06 13:37:54.865400 Mattie[1390:361681] ON PAUSE
2016-12-06 13:37:54.897354 Mattie[1390:361681] Added pause timer for 1 minutes
Planned in at 13:36:48, called at 13:37:54
asyncAfter
is only guaranteed to wait at least as long as specified.
You probably should still be using Timer if you want exact time intervals on iOS9.
Timer.scheduledTimer(timeInterval: delay,
target: self,
selector: #selector(executeClosure),
userInfo: nil,
repeats: false)
With executeClosure being a function that executes the last saved closure.
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