Поведение задачи загрузки фонового 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()
}

Обратите внимание, что я не устанавливаюсобственность напотому что я хотел бы, чтобы загрузка началась как можно скорее без каких-либо задержек. Кроме того, этот же класс (мой делегат приложения WatchKit) соответствуети я реализовали . Когда происходит загрузка, я вижу вызов этих двух методов делегата. В конце, Я звонюна экземпляре, который я сохранил вмножество.

В моем тестировании (на реальных Apple Watch Ultra с watchOS 9.3.1) я заметил, что когда система выполняет фоновое обновление приложения, я всегда получаю обратный вызов для моего метода. Но когда я запускаю задачу фоновой загрузки сеанса URL-адреса (в ), я ожидал получить еще один вызовметод (с экземпляром), когда загрузка была завершена, но это не происходит постоянно. Иногда я это вижу, но иногда нет, а когда нет, кажется, что данные не загружаются.

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

Я ошибаюсь, ожидая, что я всегда должен получать обратный вызовкогда завершается задача загрузки сеанса фонового URL-адреса? Если да, то при каких обстоятельствах это должно произойти? Большое спасибо!

0 ответов

Другие вопросы по тегам