Почему таймер вызывает его блок так быстро иногда - PullRequest
0 голосов
/ 05 декабря 2018

Я создаю таймер и вызываю его блок каждые 5 секунд.Затем я подаю заявку на ввод фона и через некоторое время на передний план.Но иногда это может быстро вызвать блок.

let _ = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { (timer) in
        print("--------")
   }

Когда я выхожу на передний план, интервал между первой и второй печатью иногда может быть меньше секунды.Является ли интервал времени недействительным в этом случае?

Ответы [ 2 ]

0 голосов
/ 29 мая 2019

Чтобы понять поведение, вам нужно понять, как работают 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().Затем создайте новый таймер для обработки событий на переднем плане.

0 голосов
/ 28 мая 2019

Когда приложение переходит в фоновый режим, оно вскоре будет приостановлено, программа остановится.Когда приложение переключается обратно на передний план, запускается событие таймера с буферизацией / задержкой, и вы быстро видите много отпечатков.

...