Как ведет себя NSTimer, когда приложение находится в фоновом режиме?

Я знаю, что когда вы запускаете приложение в фоновом режиме, таймер перестает работать. Однако каково поведение, когда вы возвращаетесь с заднего плана? Сохраняет ли таймер исходное значение fireDate?

Я столкнулся с небольшой проблемой, когда после возвращения из фона с NSTimer, настроенным на срабатывание через десять минут, иногда у меня сразу же срабатывает таймер еще до того, как applicationWillEnterForeground: будет вызван. Когда он не срабатывает и вызывается applicationWillEnterForeground:, у меня есть некоторая логика, чтобы проверить, прошли ли 10 минут, сравнивая fireDate таймера с текущей датой, однако, даже если прошло 10 минут, это всегда дает мне значение около 525 секунд в будущем от текущей даты.

Моя теория следующая:

  • NSTimer запустит таймер при возвращении из фонового режима, если вы не пропустите запланированное время больше, чем было запланировано изначально. (В этом случае мы устанавливаем таймер на 10 минут, если вы находитесь в фоновом режиме в течение 10-20 минут, он сработает при повторном входе в приложение.)

  • Если прошло больше, он не срабатывает, а вместо этого назначает другой таймер на тот же период времени в будущем, когда вы вернетесь. (AKA. Если вы были в фоновом режиме более 20 минут с 10-минутным таймером, когда вы вернетесь, он запланирует таймер на 10 минут в будущем с момента вашего возвращения в приложение.)

У кого-нибудь есть документация по этому поведению? Мои теории основаны исключительно на наблюдениях, документации о том, что происходит при фоновом режиме, либо катастрофически не хватает, либо я не смог ее найти.


person Bill L    schedule 13.05.2016    source источник


Ответы (2)


Вы правильно заметили, как ведет себя NSTimer.

Если вы прямо сейчас создадите таймер, который должен срабатывать каждые десять минут, он будет пытаться срабатывать через десять минут, 20 минут, 30 минут и так далее. Если приложение переходит в спящий режим через одну минуту и ​​просыпается через 12 минут, таймер сработает немедленно, а затем снова через 20 минут (не через десять минут после срабатывания таймера, а через 20 минут после исходного времени).

Но если таймер полностью пропускает одно событие, а затем опаздывает и для следующего события таймера, скажем, если вы просыпаетесь через 29 минут, то 10-минутное событие отбрасывается, 20-минутное событие запускается как можно скорее (через 29 минут). минут), а 30-минутное событие запускается через 30 минут.

person gnasher729    schedule 13.05.2016
comment
Это отражено в документах NSTimer: если таймер срабатывает в определенное время и каждые 5 секунд после этого запланированное время срабатывания всегда будет совпадать с исходными 5-секундными временными интервалами, даже если фактическое время срабатывания задерживается. Если время срабатывания задерживается настолько, что превышает одно или несколько запланированных значений времени срабатывания, таймер срабатывает только один раз за этот период времени; затем таймер после срабатывания переназначается на следующее запланированное время срабатывания в будущем. - person joakim; 31.01.2018
comment
Любая идея об одноразовых (неповторяющихся) таймерах? Они тоже будут стрелять по возвращении на передний план, вне зависимости от времени нахождения в БГ? Кроме того, некоторые приложения циклически работают в фоновом режиме — все медиаплееры, телефонные приложения и тому подобное. Будут ли эти приложения запускать таймеры в фоновом режиме? - person Motti Shneor; 26.07.2018

Вы не можете использовать таймеры для этой проблемы. Вот что я обнаружил после исследования аналогичной проблемы:

  • После того, как приложение находится в фоновом режиме около 30 секунд, таймер останавливается.
  • При повторном входе из фона таймер снова начинает срабатывать.

Что вы можете сделать, чтобы решить эту проблему и правильно добавить эту функциональность, вам нужно будет реализовать таймеры на вашем внутреннем сервере. Запустите службу, когда запустится таймер, и запустите таймер, когда приложение находится на переднем плане. Таймер позаботится о себе сам, но когда приложение закрывается или работает в фоновом режиме, в игру вступает сервер. Нажмите на услугу, чтобы узнать, сколько времени прошло, или отправьте push-уведомление, когда прошло 10 минут.

person Ahmad Ishfaq    schedule 13.05.2016
comment
Так что я думаю, что вы описываете немного другую проблему. Кажется, что таймер продолжает отслеживаться, а затем срабатывает, когда вы возвращаетесь, однако, если вы ждете достаточно долго, он, кажется, переназначает таймер, когда вы возвращаетесь, вместо того, чтобы запускать его. - person Bill L; 13.05.2016
comment
Хм, я думаю, как это работает, он останавливает таймер примерно через 30-90 секунд, а затем, если прошло определенное время, он убивает таймер. - person Ahmad Ishfaq; 13.05.2016