Лучшее место для вызова `completionHandler`, полученного в `handleEventsForBackgroundURLSession`, в случае загрузки?

Я использую URLSessionConfiguration.background для загрузки и скачивания контента, когда мое приложение не на переднем плане. Код, который я использую для создания фонового сеанса, выглядит следующим образом:

    private var session: URLSession!
    private override init() {
        super.init()

        let config = URLSessionConfiguration.background(withIdentifier: Constants.backgroundSessionIdentifer)
        config.sessionSendsLaunchEvents = true
        session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
    }

В делегате приложения я получаю обработчик завершения и сохраняю его как свойство UploadDownloadService, которое является синглтоном.

    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {

        Logger.debug(#function)
        UploadDownloadService.shared.backgroundCompletionHandler = completionHandler
    }

Я выполняю обработчик завершения в urlSessionDidFinishEvents, как Apple продемонстрировано. Мой код приведен ниже:

    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {

        Logger.debug(#function)

        delegate?.urlSessionDidFinishEventsCalled()
        DispatchQueue.main.async {
            [weak self] in
            guard let backgroundCompletionHandler = self?.backgroundCompletionHandler else {
                return
            }

            Logger.debug("Executing background completion handler.")
            backgroundCompletionHandler()
            self?.backgroundCompletionHandler = nil
            self?.delegate?.didCallBackgroundCompletionHandler()
        }
    }

Теперь я обнаружил, что urlSession(_ session:, downloadTask:, didFinishDownloadingTo location:) вызывается перед urlSessionDidFinishEvents, поэтому я уверен, что мой загруженный файл сохраняется в постоянном месте, прежде чем я вызову обработчик завершения внутри urlSessionDidFinishEvents.

Но меня смущает случай загрузки. Я не нашел ни одного метода делегата, который вызывается перед методом urlSessionDidFinishEvents. Единственный метод делегата, который я нашел для загрузки, который вызывается, когда приложение не спит, — это urlSession(_ session:, task:, didCompleteWithError:). Который называется после urlSessionDidFinishEvents.

В связи с этим сценарием у меня есть два вопроса.

1. Откуда я должен вызвать обработчик завершения, чтобы я был уверен, что вся моя постобработка выполняется после загрузки (в этом случае я хочу запросить базу данных, обновить и отправить сообщение. Я создаю приложение чата )? Можно ли отложить вызов обработчика завершения, пока я выполняю обработку, и вызывать его вне метода urlSessionDidFinishEvents?

2. Сколько примерно времени я получаю после вызова обработчика завершения?

Примечание. Перед публикацией я много погуглил и нашел один связанный вопрос ">здесь. Но единственный ответ (на данный момент) на этот пост не отвечает на мой вопрос. Поэтому я решил подробно задать вопрос (описав свой сценарий) здесь.


person Nazmul Islam    schedule 07.10.2020    source источник