Поведение задачи загрузки фонового URL-адреса в watchOS?
Я работаю над независимым приложением watchOS, которое в первую очередь предназначено для сбора и периодической отправки обновлений местоположения на сервер. Пользовательский интерфейс имеет переключатель, который позволяет пользователю включать или выключать эту возможность по своему усмотрению. Типичный сценарий использования: пользователь включает переключатель утром, переводит приложение в фоновый режим и затем занимается своими делами.
Учитывая ограничения и ограничения, связанные с фоновым выполнением в watchOS, в идеальной ситуации я мог бы загружать сохраненные обновления местоположения примерно каждые 15-20 минут. Насколько я понимаю, с активным усложнением на циферблате это должно быть возможно. Я реализовал фоновое обновление приложения (BAR), и действительно, я вижу, что это надежно запускается каждые 15-20 минут или около того.
Когда происходит BAR, это приводит к обратному вызову моего метода, который определен в моем делегате приложения WatchKit следующим образом:
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
backgroundTasks.forEach { task in
switch task {
case let appRefreshBackgroundTask as WKApplicationRefreshBackgroundTask:
// start background URL session to upload data; watchOS will perform the
// request in a separate process so that it will continue to run even if
// our app gets terminated; when the system is done transferring data, it
// will call this method again and backgroundTasks will contain an instance
// of WKURLSessionRefreshBackgroundTask which will be processed below
startBackgroundURLSessionUploadTask()
scheduleNextBackgroundAppRefresh()
appRefreshBackgroundTask.setTaskCompletedWithSnapshot(false)
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
// add urlSessionTask to the pendingURLSessionRefreshBackgroundTasks array
// so we keep a reference to it; when the system completes the upload and
// informs us via a URL session delegate method callback, then we will
// retrieve urlSessionTask from the pendingURLSessionRefreshBackgroundTasks
// array and call .setTaskCompletedWithSnapshot(_:) on it
pendingURLSessionRefreshBackgroundTasks.append(urlSessionTask)
// create another background URL session using the background task’s
// sessionIdentifier and specify our application delegate as the session’s
// delegate; using the same identifier to create a second URL session allows
// the system to connect the session to the upload that it performed for us
// in another process
let configuration = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier)
let _ = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
default:
task.setTaskCompletedWithSnapshot(false)
}
}
}
Итак, как вы можете видеть, когда я обрабатываю фоновую задачу обновления приложения, я создаю и возобновляю новую фоновую задачу загрузки сеанса URL-адреса. Вот как это выглядит:
func startBackgroundURLSessionUploadTask() {
// 1. check to see that we have locations to report; otherwise, return
// 2. serialize the locations into a temporary file
let configuration = URLSessionConfiguration.background(withIdentifier: Constants.backgroundUploadIdentifier)
configuration.isDiscretionary = false
configuration.sessionSendsLaunchEvents = true
let backgroundUrlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let request: URLRequest = createURLRequest()
let backgroundUrlSessionUploadTask = backgroundUrlSession.uploadTask(with: request, fromFile: tempFileUrl)
// on average, we'll send ~1.5KB - 2.0KB of data
backgroundUrlSessionUploadTask.countOfBytesClientExpectsToSend = Int64(serializedData.count)
// the server response is ~50 bytes
backgroundUrlSessionUploadTask.countOfBytesClientExpectsToReceive = Int64(50)
backgroundUrlSessionUploadTask.resume()
}
Обратите внимание, что я не устанавливаю
В моем тестировании (на реальных Apple Watch Ultra с watchOS 9.3.1) я заметил, что когда система выполняет фоновое обновление приложения, я всегда получаю обратный вызов для моего метода. Но когда я запускаю задачу фоновой загрузки сеанса URL-адреса (в ), я ожидал получить еще один вызов
Кстати, в большинстве случаев вызывается в результате того, что мой код обрабатывает задачу обновления фонового приложения. Но когда пользователь выключает переключатель в пользовательском интерфейсе и я останавливаю обновления местоположения, мне нужно сообщить о любых сохраненных местоположениях в это время, и поэтому я вызываю
Я ошибаюсь, ожидая, что я всегда должен получать обратный вызов