Можно ли выполнить что-то в основном потоке после вызова didEnterBackground? - PullRequest
1 голос
/ 09 мая 2020

Прежде всего, я хотел бы извиниться, если вы считаете мой вопрос пустышкой, я новичок в 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) или он будет выполнен после пользователь вернется в приложение или оно будет удалено? Или такая ситуация вообще невозможна? Спасибо за вашу помощь и еще раз извините, если мой вопрос неверен.

1 Ответ

1 голос
/ 09 мая 2020

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

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

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

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

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

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

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

На этом шаге вы должны приостановить выполнение текущей задачи, поскольку Apple говорит: «Вы должны сделать ваше приложение тихим

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

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

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

  • Аннулировать все активные таймеры.

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

  • ...

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

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

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

...