Чтобы понять поведение, вам нужно понять, как работают NSTimer
и RunLoop
.Проще говоря, RunLoop
будет проверять, должен ли Таймер срабатывать, если да, он уведомит Таймер о срабатывании селектора, иначе он не будет.Теперь, когда вы находитесь в фоновом режиме, ваш RunLoop
не проверяет события, поэтому он не сможет уведомить таймер.Но как только он выйдет на передний план, он увидит, что ему нужно будет уведомить Таймер, даже если он прошел fireDate.
Диаграмма Времени:
Позвольте A (5-я секунда) и B (10-я)во-вторых) быть таймером огня событий.Запланировано по таймеру Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true)
C вводится в фоновом режиме (0 секунд)
D возвращается на передний план (9-я секунда, между A и B).
-----> A ------> B
C ---------> D
Пояснение:
На C,RunLoop будет приостановлен.Следовательно, событие A не может быть обработано до тех пор, пока RunLoop не возобновит обработку, которая находится на событии D. После события D он увидит, что событие A должно сработать, чтобы уведомить об этом таймер.Через секунду RunLoop увидит, что событие B произошло, и снова уведомит таймер.Этот сценарий объясняет, почему ваши события печатаются с интервалом в секунду.Именно задержанная обработка события создает впечатление, что оно сработало раньше, когда на самом деле оно было обработано с опозданием.
Apple Doc:
Таймер не работает в режиме реального временимеханизм.Если время срабатывания таймера происходит во время обратного вызова цикла длительного выполнения или когда цикл выполнения находится в режиме, который не контролирует таймер, таймер не срабатывает, пока в следующий раз цикл выполнения не проверит таймер.Таким образом, фактическое время срабатывания таймера может быть значительно позже.
resources: Что такое поведение NSTimer, когда приложение работает в фоновом режиме? , NSRunLoop и Timer Docs
Предложения:
Остановите таймер, как только приложение выйдет в фоновом режиме, но сохраните fireDate
.Вернувшись на передний план, проверьте, не прошло ли fireDate
Date()
.Затем создайте новый таймер для обработки событий на переднем плане.