Фоновый сетевой вызов из фонового ввода

У меня есть приложение, которое общается с Apple Watch. Когда основное приложение iOS получает удаленное уведомление, оно запускает сетевой запрос с помощью URLSession а затем также отправляет результат на часы.

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

У меня есть набор флагов контента, и я также попытался использовать URLSessionConfiguration.background без успеха.

 var config:URLSessionConfiguration! var session:URLSession? private func configureSession() { self.config = URLSessionConfiguration.background(withIdentifier: "backgroundFetch") //self.config = URLSessionConfiguration.default self.config.sessionSendsLaunchEvents = true self.config.timeoutIntervalForRequest = 15.0 self.config.timeoutIntervalForResource = 15.0 self.session = URLSession(configuration: self.config, delegate: self, delegateQueue: nil) } 

Вы можете видеть выше, что я пробовал его как по умолчанию, так и в фоновом режиме.

 func getCoordinatesForID(_ trackID:String, withPassCode passCode:String, andMyID myID:String) { let url = self.WEB_DOMAIN+"getcoord" let hash = SecurityModel.sha256(myID+trackID+passCode)! var request = URLRequest(url: URL(string: url)!) request.httpMethod = "POST" request.setValue("application/x-www-form-urlencoded;charset=utf-8", forHTTPHeaderField: "Content-Type") let postDataStr = "auth=\(hash)&id=\(myID)&trk=\(trackID)&code=\(passCode)" let requestBodyData = postDataStr.data(using: String.Encoding.utf8) request.httpBody = requestBodyData let postDataTask = self.session!.dataTask(with: request) postDataTask.taskDescription = "getCoordinates" postDataTask.resume() } 

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

Я реализую ниже, ни один из них не вызывается в фоновом режиме.

 func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) 

а также

 func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 

Обновить:

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

 func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 

Вышеупомянутое вызывается, но вызывает ошибку: "Lost connection to background transfer service" . Выполняется в 100% случаев, когда в фоновом режиме, но не на переднем плане.

  func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) 

Вышеупомянутое, которое мне нужно и которое вызывается первым перед вышеописанным методом, вообще не называется. Таким образом, общие вещи продвинулись немного дальше, но все же не работают так же, как и на переднем плане.

Решение:

Решение заключалось в том, чтобы удалить timeoutIntervalForRequest и timeoutIntervalforResource Несмотря на то, что я никогда не ждал 15 секунд, которые я установил до появления проблемы, их удаление позволило корректно работать в фоновом режиме. Кроме того, я могу использовать стандартный URLSessionConfiguration.default а не .background.

Таким образом, в конце добавления возможности «фоновой выборки» и устранения тайм-аутов была решена проблема.

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

Задачи данных запрашивают ресурс, возвращая ответ сервера как один или несколько объектов NSData в памяти. Они поддерживаются в дефолтных, эфемерных и общих сеансах, но не поддерживаются в фоновых сеансах.

Чтобы решить эту проблему, мне пришлось создать URLSessionDownloadTask и использовать связанный с ней делегат

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)

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