Я пытаюсь вызвать функцию после задержки. На iOS10 я могу использовать Timer.scheduledTimer, который действительно вызывает мое закрытие после данной задержки. Однако на iOS9 я использую DispatchQueue.main.asyncAfter, и он вызывает мое закрытие с задержкой в шесть секунд.DispatchQueue.main.asyncAfter неточно
Задержка, которую я тестирую, составляет 60 секунд. Timer.scheduledTimer вызывает закрытие через 60 секунд, DispatchQueue.main.async Через 66 секунд. Задержка в шесть секунд является следствием, если я планирую два задержек на 60 секунд, вторая задержка вызывается через 132 секунды, используя 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()
}
}
}
Код, который вызывает функцию задержки:
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.")
}
уведомления и методы планирования вызовов с использованием 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.
Пауза называется:
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
Запланированные в 13:34 : 06, названный в 13:35:06
уведомлений и методов планирования вызовов с использованием 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.
Пауза называется:
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
Планируемое в в 13:36: 48, позвонил по телефону 13:37:54
Спасибо, это имеет смысл. Я думаю, что происходит, что выполнение кода задерживает основной поток в течение шести секунд. Между каждым сеансом исследования и паузы я подключаюсь к VPN. Первоначально я использовал Timer для iOS9, но параметр селектора вызвал некоторые проблемы, потому что функция принимает один параметр. XCode хотел, чтобы я добавил @objc к моему методу. Я посмотрю, как разрешить это и придерживаться Timer для обеих версий iOS. –
У меня также возникла эта проблема ('asyncAfter' не точный). В моем случае было всегда поздно около 10%, чем ожидалось. Я был удивлен, что это единственное обсуждение, которое я нашел на эту тему, поэтому я просто подумал, откуда вы знаете, что «asyncAfter» гарантированно будет ждать хотя бы столько, сколько указано «@ tristan-burnside»? :) Я не мог найти официальных документов по этому вопросу. – tadija
Я тоже был в этой проблеме, пытаясь обобщить некоторые функции отсрочки события и хотел, чтобы это было сделано с помощью gcd, но в конечном итоге я использовал таймер, поскольку это имеет смысл. Надеюсь, никто не будет тратить время (~ 5 часов), как я. Спасибо, Тристан –