Статьи

Что нового в watchOS 3: фоновые задачи

С предстоящим обновлением watchOS 3 для всех устройств Apple Watch производительность многих часовых приложений значительно улучшится. Это происходит главным образом из-за новых форм фонового выполнения, которыми могут пользоваться приложения watchOS для периодического обновления своего контента и получения самой последней информации, готовой для просмотра пользователем.

В этом уроке я покажу вам, как вы можете использовать новые API WatchKit в watchOS 3, чтобы ваше собственное приложение использовало эти новые фоновые задачи. Важно отметить, что, даже если ваше приложение настроено должным образом для поддержки этих фоновых обновлений, в зависимости от конфигурации конкретного пользователя, система может не позволить вашему приложению работать в фоновом режиме.

Это руководство требует, чтобы вы работали с Xcode 8 на OS X El Capitan или более поздней версии.

Первым важным новым классом в watchOS 3 является класс WKRefreshBackgroundTask . Это абстрактный класс, который вы не должны создавать подклассами или создавать свои собственные экземпляры. Он определяет только одно свойство userInfo , которое может хранить дополнительную информацию, относящуюся к фоновой задаче. Он также определяет единственный метод setTaskCompleted() , который вы должны вызвать сами, чтобы сообщить системе, что задача выполнена. Если вы не позвоните по этому номеру, то система потратит максимальное количество времени, заложенное в бюджете на ваше приложение, пытаясь выполнить задачу, что, в свою очередь, расходует заряд батареи и снижает производительность других приложений.

Когда ваше приложение должно обработать выполнение фоновой задачи, система вызовет метод handle(_:) вашего делегата расширения watchOS. Единственный параметр этого метода — это набор объектов WKRefreshBackgroundTask которые необходимо циклически обработать и обработать соответствующим образом.

В рамках WatchKit Apple предоставляет следующие четыре конкретных подкласса; watchOS передаст вашему расширению делегировать экземпляр соответствующего класса в зависимости от задачи.

  • WKApplicationRefreshBackgroundTask — это общий тип фоновой задачи, который не специализирован для определенного типа обновления. Наиболее распространенный вариант использования этого типа — для планирования других задач. Например, вы можете запланировать фоновое обновление для своего приложения на определенное время дня каждый день. Когда соответствующий объект WKApplicationRefreshBackgroundTask затем передается в метод handle(_:) вашего делегата расширения, вы можете создать фоновую сетевую задачу, чтобы загрузить некоторые данные для обновления содержимого вашего приложения.
  • WKSnapshotRefreshBackgroundTask — это тип задачи, специально предназначенный для WKSnapshotRefreshBackgroundTask когда вашему приложению необходимо обновить свой снимок. Мы обсудим снимки позже в этом уроке. Все, что вам нужно знать на данный момент, — это то, что снимок приложения используется в качестве образа запуска и может также отображаться в доке пользователя (доступ к которому можно получить, нажав боковую кнопку). Обратите внимание, что этот тип фоновой задачи имеет уникальный метод завершения задачи, который мы также обсудим позже.
  • WKWatchConnectivityRefreshBackgroundTask — это тип задачи, когда вы переносили данные со своего iPhone на часы через платформу WatchConnectivity. Поскольку эта структура предоставляет метод для передачи данных о сложностях непосредственно в часы, этот соответствующий тип фоновой задачи в основном используется для планирования обновлений моментальных снимков в ответ на данные, полученные от iPhone.
  • WKURLSessionRefreshBackgroundTask — это тип задачи, назначаемый вашему делегату расширения по завершении фоновой сетевой задачи. В этом сценарии методы делегата, настроенные вами для объекта URLSession , по-прежнему вызываются, и именно здесь вам необходимо работать с данными надлежащим образом. Метод handle(_:) вашего делегата расширения вызывается только для того, чтобы ваше приложение могло реагировать на завершение сетевой операции. WKURLSessionRefreshBackgroundTask не предоставляет вам доступ ни к объекту URLSession ни к данным, которые были переданы. Единственное дополнительное свойство, которое оно определяет, — это строка с именем sessionIdentifier которую можно использовать для определения того, какой сетевой процесс завершен.

Есть несколько способов запланировать фоновое обновление в watchOS 3. Для простого обновления приложения или моментального снимка, соответственно, вы можете использовать следующие два метода для любого объекта WKExtension .

По завершении этот метод вернет объект WKApplicationRefreshBackgroundTask вашему делегату расширения. Система watchOS будет пытаться разбудить ваше расширение в фоновом режиме во время, указанное параметром Date .

Обратите внимание, что не гарантируется, что ваше приложение будет работать в фоновом режиме именно в это время. Из-за других обстоятельств (таких как оставшийся заряд батареи, другие приложения, работающие в памяти и т. Д.) Система может принять решение разбудить ваше приложение позднее.

Параметр userInfo будет доступен через любой объект фоновой задачи, переданный вашему делегату расширения. Это может быть особенно полезно, если вам нужно отправить информацию, относящуюся только к текущему обновлению. Наконец, параметр scheduledCompletion может предоставить блок кода, который будет запущен после того, как обновление было запланировано или произошло сбой из-за какой-либо ошибки.

Этот метод возвращает объект WKSnapshotRefreshBackgroundTask вашему делегату расширения. Параметры для этого метода идентичны при планировании регулярного обновления приложения. Единственное отличие этого метода заключается в типе обновления, которое вы планируете.

Ниже приведен пример кода, который можно использовать в любом месте приложения WatchOS для планирования фонового обновления:

1
2
3
4
5
WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: Date(timeIntervalSinceNow: 60 * 60), userInfo: nil) { (error: Error?) in
    if let error = error {
        print(«Error occurred while scheduling background refresh: \(error.localizedDescription)»)
    }
}

Как упоминалось ранее, WKWatchConnectivityRefreshBackgroundTask создается в ответ на отправку данных на часы с сопряженного iPhone через API-интерфейсы WatchConnectivity.

Последний тип фоновой задачи, WKURLSessionRefreshBackgroundTask , автоматически назначается системой при создании объекта URLSession с фоновой конфигурацией. Выполнение этого из любого места в вашем приложении наблюдения приведет к тому, что система автоматически запланирует запрос для вас и вызовет метод handle(_:) вашего добавочного абонента, когда он будет завершен. Следующий пример кода содержит две функции в примере класса. Первая функция настраивает и запускает задачу фоновой загрузки. Второй — это метод делегата, объявленный в протоколе URLSessionDelegate .

01
02
03
04
05
06
07
08
09
10
11
12
class SomeClass: URLSessionDelegate {
    func beginDownloadTask() {
        let config = URLSessionConfiguration.background(withIdentifier: «exampleSessionIdentifier»)
        let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
        let task = session.downloadTask(with: URL(string: «http://www.example.com/data»)!)
        task.resume()
    }
 
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        print(«Session did complete»)
    }
}

В watchOS 3 взгляды приложений были полностью удалены из Apple Watch и заменены док-станцией . Доступ к этой док-станции осуществляется нажатием боковой кнопки на часах и содержит любое количество приложений, которые пользователь может настроить:

WatchOS 3 Док

Если ваше приложение было помещено в док-станцию ​​пользователя, вы несете ответственность за актуальность видимого «снимка», отображаемого в док-станции.

Ваше приложение уведомляется, когда вам необходимо обновить снимок с помощью WKSnapshotBackgroundRefreshTask , передаваемого в метод handle(_:) вашего делегата расширения. Когда вы получаете это уведомление, помимо пробуждения расширения WatchKit в фоновом режиме, контроллер корневого интерфейса вашего приложения также пробуждается в фоновом режиме и за его пределами. В этом процессе в следующем порядке вызываются следующие методы:

  1. awake(withContext:) контроллера корневого интерфейса awake(withContext:) метод
  2. Метод willActivate() контроллера корневого интерфейса
  3. Дескриптор делегата расширения handle(_:) метод handle(_:)

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

Последний шаг обновления снимка происходит в методе handle(_:) делегата расширения handle(_:) . Как и с другими типами фоновых задач, вы должны сообщить системе, что задача выполнена. Однако для обновления снимка это делается путем вызова setTaskCompleted(restoredDefaultState:estimatedSnapshotExpiration:userInfo:) объекта WKSnapshotBackgroundRefreshTask . Как только вы вызываете этот метод, watchOS делает снимок текущего интерфейса вашего приложения и сохраняет его в памяти до следующего обновления. Чтобы лучше понять этот метод, давайте рассмотрим все его параметры:

  • restoredDefaultState — это просто логическое значение, указывающее, относится ли ваш снимок к первому контроллеру интерфейса вашего приложения. Если вы перешли на другой интерфейс, передайте значение false для этого значения.
  • estimatedSnapshotExpiration — это объект Date который указывает, когда система должна в следующий раз попытаться обновить снимок вашего приложения. Если вам не нужно планировать другое обновление немедленно, вы можете передать новое Date.distantFuture класса Date.distantFuture .
  • userInfo — это коллекция пользовательских данных, которая будет передана в следующий объект WKSnapshotBackgroundRefreshTask если вы сразу запланируете другое обновление.

Инфраструктура WatchConnectivity, представленная в watchOS 2 и iOS 9, также получает некоторые новые функциональные возможности в watchOS 3 и iOS 10.

Если пользователь поместил услугу вашего приложения на циферблат, вы можете передавать данные с телефона на часы до 50 раз в течение одного дня. Это делается, как в iOS 9 и watchOS 2, с помощью метода экземпляра WCSession transferCurrentComplication(userInfo:) . Новым в watchOS 3 и iOS 10 WCSession свойство WCSession , которое сообщит вам, сколько передач осталось на этот день.

Еще одно новое свойство WCSession добавленное с обновлениями платформы этого года, — это свойство hasContentPending , которое является просто логическим значением, hasContentPending , есть ли еще данные, которые должны быть переданы между iPhone и Apple Watch.

Если вы хотите узнать больше о WatchConnectivity и о том, как он работает, вы можете ознакомиться с нашими предыдущими руководствами, посвященными этой платформе.

  • watchOS 2: общение с коллегой

  • watchOS 2: фоновые передачи и очереди

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

Связанное репозиторий GitHub содержит проект watchOS 3 Xcode с примером кода, показывающего, как вы можете планировать и реагировать на фоновые обновления в ваших собственных приложениях.

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