Можно ли выполнить что-то в основном потоке после вызова didEnterBackground?

Прежде всего, я хотел бы извиниться, если вы считаете мой вопрос фиктивным, я новичок в iOS и многопоточности и просто хочу понять, как обстоят дела. Насколько я знаю, didEnterBackground — это последняя функция, которую iOS вызывает перед приостановкой приложения, и у приложения есть около 5 секунд, чтобы вернуться из нее, иначе iOS убьет приложение. В настоящее время я думаю о такой ситуации - у меня есть какая-то задача, которая выполняется в фоновом потоке (например, загрузка по сети), а ее блок завершения происходит в основном потоке. как это

fun downloadData() {
  Downloader.download(url: "someUrl") { [weak self] in // download is on the background thread
    DispatchQueue.main.async { [weak self] in // switch to main
      // do some stuff
    }
  }
}

downloadData() в настоящее время работает в фоновом потоке, пользователь нажимает кнопку «Домой», и приложение переходит в фоновый режим, и вызывается didEnterBackground. В то время как основной поток выполняет код в didEnterBackground downloadData завершает загрузку, вызывается его завершение, и новая задача помещается в очередь основных потоков. Так что же будет в этом случае? Поскольку код из didEnterBackground является последним, который может быть выполнен перед приостановкой, что произойдет с блоком завершения downloadData, будет ли он также выполняться до приостановки (после didEnterBackground) или он будет выполняться, когда пользователь вернется в приложение? , или он будет отброшен? Или такая ситуация вообще невозможна? Спасибо за помощь и еще раз извините, если мой вопрос некорректен.


person starwarrior8809    schedule 08.05.2020    source источник


Ответы (1)


Прежде всего, я предлагаю вам рассмотреть этот документ, предоставленный Apple. Документ сам по себе ясен, но я просмотрю его, чтобы извлечь важную информацию, соответствующую вашему вопросу.

В этом документе Apple прямо говорит, что каждая приостановленная задача пользовательского интерфейса будет отброшена, и вы не должны отправлять новые задачи в очереди отправки, и вам следует приостановить текущие очереди и освободить ресурсы как можно скорее. .

Когда приложение должно быть деактивировано, есть два шага:

  1. Системные вызовы приложения applicationWillResignActive(_:) метод (или sceneWillResignActive(_:), если вы используете sceneDelegate)
  2. Затем UIKit вызывает метод applicationDidEnterBackground(_:) (или sceneDidEnterBackground(_:))

На первом этапе UIKit уведомляет вас о деактивации, что означает, что через несколько раз приложение перейдет в фоновый режим. На этом этапе вы должны сохранить все конфиденциальные данные.

На этом этапе, если вы приостановили задачи пользовательского интерфейса, все они будут удалены.

Система также деактивирует приложения, когда необходимо временно прервать их работу, например, для отображения системных предупреждений.

На этом этапе вы должны приостановить текущую задачу. Как говорит Apple, вы должны сделать свое приложение тихим.

  • Сохраните пользовательские данные на диск и закройте все открытые файлы.

  • Приостановить очереди отправки и операций.

  • Не планируйте новые задачи для выполнения.

  • Сделайте недействительными все активные таймеры.

  • Автоматическая пауза в игре.

  • ...

На втором этапе, когда UIKit уведомляет ваше приложение о переносе фонового состояния tp, вы должны как можно быстрее освободить общие ресурсы. Если вы продолжите использовать ресурсы, ваше приложение будет прекращено.

Поэтому упомянутая в вашем вопросе задача пользовательского интерфейса будет отклонена.

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

person Mahsa Yousefi    schedule 09.05.2020