Статьи

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

Watch Connectivity — это новая коммуникационная среда, выпущенная вместе с iOS 9 и watchOS 2. Ее основная цель — легко и без проблем передавать информацию между приложением Apple Watch и его родительским приложением iOS.

Фреймворк предоставляет множество различных функций. Несколько недель назад Хорхе Коста писал о возможности отправки сообщений между iOS и приложением Apple Watch. В этом уроке мы рассмотрим передачу данных в фоновом режиме.

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

Это руководство требует, чтобы вы работали с Xcode 7 в OS X 10.10 или более поздней версии. Вам также необходимо скачать стартовый проект с GitHub .

Чтобы использовать платформу Watch Connectivity, ваше приложение для iOS и watchOS должно иметь класс, соответствующий протоколу WCSessionDelegate и правильно настраивающий WCSession по умолчанию. Методы протокола WCSessionDelegate обрабатывают получение всех данных через платформу Watch Connectivity и позволяют вам контролировать новые данные в вашем приложении.

Откройте стартовый проект в XCode и отредактируйте AppDelegate.swift . Вверху добавьте следующий оператор import :

1
import WatchConnectivity

Затем обновите определение класса класса AppDelegate чтобы привести его в соответствие с протоколом WCSessionDelegate .

1
class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate {

Мы также объявляем свойство типа WCSession! в классе AppDelegate для хранения ссылки на объект WCSession по умолчанию.

1
var session: WCSession!

Наконец, обновите application(_:didFinishLaunchingWithOptions:) как показано ниже.

01
02
03
04
05
06
07
08
09
10
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    session = WCSession.defaultSession()
    session.delegate = self
     
    if WCSession.isSupported() {
        session.activateSession()
    }
     
    return true
}

В application(_:didFinishLaunchingWithOptions:) мы получаем ссылку на объект WCSession по умолчанию, устанавливаем делегата AppDelegate экземпляра AppDelegate вашего приложения и, если поддерживается, активируем сеанс. isSupported класса isSupported проверяет, установлено ли на сопряженных Apple Watch совместимое приложение watchOS для вашего приложения iOS и может ли оно отправлять данные.

Настройка для стороны watchOS очень похожа. Откройте ExtensionDelegate.swift и замените его содержимое следующим:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
import WatchKit
import WatchConnectivity
 
class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate {
     
    var session: WCSession!
 
    func applicationDidFinishLaunching() {
        session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
 
    func applicationDidBecomeActive() {
         
    }
 
    func applicationWillResignActive() {
         
    }
}

Вы заметите, что мы не вызываем isSupported в классе WCSession до активации сеанса. Это потому, что этот метод всегда возвращает true на стороне watchOS.

Чтобы убедиться, что все работает правильно, запустите приложение Apple Watch на любом из двух симуляторов, как показано ниже.

Симуляторы Apple Watch

Затем запустите приложение iOS на том же типе симулятора iPhone, который вы выбрали при запуске приложения для часов.

iOS симуляторы

После запуска приложения для iOS симулятор Apple Watch должен вернуться к циферблату, как показано на скриншоте ниже.

iOS-приложение и симулятор Apple Watch

При правильно настроенном объекте WCSession по умолчанию WCSession пора отправить некоторые данные между iOS и приложением Apple Watch.

Откройте TableViewController.swift и добавьте следующую строку кода в конец метода createNewItem(_:) :

1
WCSession.defaultSession().transferUserInfo(item)

Метод transferUserInfo(_:) принимает словарь в качестве единственного параметра. Как только этот метод был вызван, предоставленный вами информационный словарь пользователя добавляется в очередь передаваемой информации.

И iOS, и watchOS работают совместно друг с другом для передачи информации в удобное время. Объединенная система смотрит на такие вещи, как использование приложения, время автономной работы, используется ли в данный момент другое устройство и т. Д. Как только система передаст информацию, приложение на другом устройстве выполнит метод обратного вызова делегата в следующий раз запущен.

Теперь пришло время внедрить принимающую сторону в Apple Watch. Откройте ExtensionDelegate.swift и добавьте следующий метод в класс ExtensionDelegate :

01
02
03
04
05
06
07
08
09
10
11
func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
    dispatch_async(dispatch_get_main_queue()) { () -> Void in
        if let items = NSUserDefaults.standardUserDefaults().objectForKey(«items») as?
            var newItems = items
            newItems.append(userInfo)
            NSUserDefaults.standardUserDefaults().setObject(newItems as AnyObject, forKey: «items»)
        } else {
            NSUserDefaults.standardUserDefaults().setObject([userInfo] as AnyObject, forKey: «items»)
        }
    }
}

Этот метод будет вызван, как только мы запустим приложение Apple Watch и когда информация будет успешно передана.

Обратите внимание, что хотя в этом руководстве показан только пример передачи информации из iOS в watchOS, методы WCSession и WCSessionDelegate ведут себя одинаково на обеих платформах для фоновой передачи.

С помощью этого кода запустите приложение Apple Watch в симуляторе. Затем снова запустите приложение iPhone и нажмите кнопку, чтобы создать новый элемент.

Создание элемента на стороне iOS

Теперь вернитесь к симулятору Apple Watch и дважды нажмите Command-Shift-H, чтобы вернуться к последнему приложению. Вы увидите, что только что созданный элемент отображается на Apple Watch.

Предмет, показывающий на часах

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

Если приложение для iOS все еще работает, выйдите из симулятора Apple Watch из строки меню или нажав Command-Q . После этого нажмите кнопку в приложении iOS, чтобы создать еще несколько элементов, как показано ниже.

Дополнительные элементы iOS

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

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

Откройте AppDelegate.swift и добавьте следующий код в конце application(_:didFinishLaunchingWithOptions:) :

1
2
3
4
5
let transfers = session.outstandingUserInfoTransfers
if transfers.count > 0 {
    let transfer = transfers.first!
    transfer.cancel()
}

С помощью этого кода мы получаем доступ к ожидающим передачам информации пользователя и, если есть хотя бы один, отменяем первый перевод. Объекты WCSessionUserInfoTransfer возвращаемые из свойстваraldUserInfoTransfers, также имеют два свойства только для чтения, к которым можно получить доступ:

  • userInfo : Это свойство хранит словарь, который вы переводите.
  • transferring : это свойство хранит логическое значение и указывает, передается ли информация о пользователе в данный момент.

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

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

Это где вам нужно передавать информацию между устройствами, где актуальна только самая свежая информация. Вы передаете один словарь, вызывая метод updateApplicationContext(_:error:) . Параметр error в этом методе является указателем на объект NSError , который будет заполнен информацией, если возникнет проблема с передачей.

На принимающей стороне вы можете реализовать метод session(_:didReceiveApplicationContext:) или, в качестве альтернативы, получить доступ к контексту приложения через WCSession объекта WCSession по умолчанию.

Это где вам нужно перенести один пользовательский словарь информации специально для пользовательского сложности вашего приложения. Вы можете отправлять информацию только со стороны iOS, и это делается с помощью метода transferCurrentComplicationUserInfo(_:) .

Основное различие между этим и методом transferUserInfo(_:) использованным ранее в этом руководстве, заключается в том, что при обновлении сложности система всегда будет пытаться немедленно передать информацию.

Обратите внимание, что передача не гарантируется, так как устройства могут быть отключены или ваша сложность может превысить его фоновый бюджет выполнения. Если передача информации о сложности не может быть завершена, она добавляется в очередь outstandingUserInfoTransfers InfoTransfers, где ее можно просмотреть и отменить при необходимости.

Также обратите внимание, что если передача информации о сложностях находится в очереди и вы снова вызываете метод transferCurrentComplicationUserInfo(_:) , существующий перевод в очереди будет аннулирован и отменен.

Вы даже можете использовать платформу Watch Connectivity для передачи файлов между устройствами. Это делается с помощью метода transferFile(_:metaData:) где первый параметр — это локальный NSURL для файла, а второй — необязательный словарь, содержащий любые дополнительные данные, связанные с этим файлом.

Как и следовало ожидать, получение этого файла обрабатывается методом протокола WCSessionDelegate , WCSessionDelegate , session(_:didReceiveFile:) методом. В этом методе вам предоставляется один объект WCSessionFile который содержит новый локальный URL-адрес фактического файла, а также метаданные, которые вы передали.

Как и в случае передачи информации о пользователе, вы также можете просматривать ожидающие или передаваемые файлы, которые выполняются с помощью WCSession объекта WCSession по умолчанию.

В целом платформа Watch Connectivity предоставляет очень простой и удобный интерфейс для передачи данных между подключенным iPhone и Apple Watch. Инфраструктура позволяет передавать информацию о пользователях, контексте приложения и информационных словарях сложности, а также файлы.

Теперь вам должно быть удобно отправлять и получать информацию, используя платформу Watch Connectivity, а также то, как вы можете взаимодействовать с любыми невыполненными передачами.

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