watchOS 2: Cómo comunicar dispositivos usando Watch Connectivity

Como-comunicar-dispositivos-usando-Watch-Connectivity

Si has creado alguna App para el reloj de Apple, sabrás que la comunicación entre dispositivos no es fácil.

En watchOS 2 por suerte esto se ha mejorado, y podemos comunicar dispositivos usando un nuevo Framework llamado Watch Connectivity.

Esto es nuevo, y cambia por completo la forma de comunicación entre el iPhone y el Watch que existía hasta el momento.

Con watchOS 1 únicamente disponíamos de una forma de comunicación, era el método openParentApplication pero este ya no se puede usar en watchOS 2, y debemos hacer uso de la nueva librería que Apple ha creado para tal efecto.

Cómo comunicar dispositivos usando Watch Connectivity

Lo primero es crear una sesión.

Esto es muy fácil y basta con incluir esta condición en el método viewDidLoad de nuestro ViewController en la parte del iPhone, o bien en el método awayWithContext o willActivate en la parte del watch:

//Swift
if (WCSession.isSupported()) {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
//Objective-C
if ([WCSession isSupported]) {      
WCSession *session = [WCSession defaultSession];      
session.delegate = self;      
[session activateSession];
}

Con esta condición comprobamos si podemos establecer una conexión, de poder hacerlo creamos un objeto WCSession y le pasamos su delegado.

No hay que olvidar que debemos importar el Framework WatchConnectivity a nuestro proyecto, e importar la cabecera del Framework en cada una de las clases en las cuales queramos usarlo.

Basta con incluir en nuestro fichero de cabecera de la clase la linea de código:

//Objective-C
#import <WatchConnectivity/WatchConnectivity>;
//Swift
import WatchConnectivity

Enviando y recibiendo

Hay dos tipos de comunicación en WatchConnectivity.

Transferencias en background y paso de mensajes.

Tenemos tres tipos de transferencias en background, dependiendo de lo que queramos hacer usaremos una u otra.

Transferencias en background

Usaremos este tipo de comunicación cuándo queramos mantener una comunicación que no sea inmediata, ya que estos métodos los ejecutará el sistema operativo cuándo crea conveniente.

El contenido se añade a colas que el sistema operativo libera a su conveniencia.

Disponemos de tres tipos:

  • updateApplicationContext
  • transferUserInfo
  • transferFile

updateApplicationContext

Con este método podremos pasar datos de actualización.

Esto significa que sólo se envían y reciben los datos más actualizados, esta forma de comunicación es ideal si nuestra aplicación recibe datos de un servidor y sólo queremos mostrar los últimos datos recibidos al usuario.

Es decir, sólo se transfiere los últimos datos recibidos para actualizar el contexto.

Podemos hacer uso de este método de este modo:

//Swift

do {

let diccionarioDatos = // Un diccionario

try WCSession.defaultSession().updateApplicationContext(diccionarioDatos)

}

catch {

// Errores

}
//Objective-C

NSDictionary *diccionarioDatos = // Un diccionario

[[WCSession defaultSession] updateApplicationContext:diccionarioDatos error:nil];

Enviamos un diccionario, en la otra parte (ya sea en la parte del Watch o en la parte del iPhone) debemos recibirlo.

WatchConnectivity hace uso del patrón del delegado, así que recibiremos el envío a través de un método delegado, es el siguiente:

//Swift
func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) {
#code#
}
//Objective-C
-(void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary; *)applicationContext{
#code#
}

transferUserInfo

Antes hablamos del método opentParentApplication, esta era la única forma de comunicarnos entre dispositivos con watchOS 1.

Bien, pues aquí tenemos a su sustituto 😉

Podemos hacer uso de esta forma de comunicación de la siguiente manera:

//Swift
let diccionario = // Un diccionario
let transfer = WCSession.defaultSession().transferUserInfo(diccionario)

//Objective-C
NSDictionary * diccionario = // Un diccionario
[[WCSession defaultSession] transferUserInfo: diccionario];

Y en la otra parte, para recibir:

//Swift
func session(session: WCSession,
didReceiveUserInfo userInfo: [String : AnyObject]){
}
//Objective-C
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary *)userInfo{
}

transferFile

Tercera y última forma de comunicación en background.

Usaremos transferFile para enviar y recibir cualquier tipo de archivo entre dispositivos.

Esta es la forma de uso:

//Swift
let url = // URL
let diccionario = // Un diccionario 
let fileTransfer = WCSession.defaultSession().transferFile(url,
metadata:diccionario)

//Objective-C
NSURL *url = // URL
NSDictionary *diccionario = // Un diccionario 
WCSessionFileTransfer *fileTransfer = [[WCSession defaultSession] transferFile:url metadata: diccionario];

También usaremos un método delegado para recibir el archivo en cuestión.

//Swift
func session(session: WCSession,
didReceiveFile file: WCSessionFile){
}
//Objective-C
- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file{
}

Paso de mensajes

Este tipo de comunicación es inmediata.

Es un paso de mensajes de un dispositivo a otro.

Para que este tipo de comunicación funcione, el watch debe estar emparejado con el iPhone, y con el BlueTooth activado en ambos dispositivos, para hacer esta comprobación usaremos la propiedad reachable.

Tenemos dos formas de pasar mensajes:

  • sendMessage
  • sendMessageData

La diferencia entre uno y otro es que con el primero enviaremos un diccionario, y en el segundo método podemos pasar un objeto de la clase NSData.

sendMessage

Podemos enviar un diccionario.

Lo haremos de la siguiente manera:

//Swift
let diccionario = // Un diccionario
WCSession.defaultSession().sendMessage(diccionario,
       replyHandler: { ([String : AnyObject]) ? Void in
          // Recibimos la respuesta
       })
        errorHandler: { (NSError) ? Void in
          // Errores
});

//Objective-C
NSDictionary * diccionario = // Un diccionario
[[WCSession defaultSession] sendMessage: diccionario
                           replyHandler:^(NSDictionary *replyHandler) {
                           // Recibimos la respuesta
                           }
                           errorHandler:^(NSError *error) {
                             // Errores
                           }
];

sendMessageData

Para enviar un objeto de la clase NSData, lo haremos así:

//Swift
let nsdataObject = // Objeto NSData
WCSession.defaultSession().sendMessageData(nsdataObject,
       replyHandler: { ([String : AnyObject]) ? Void in
          // Recibimos la respuesta
       })
        errorHandler: { (NSError) ? Void in
          // Errores
});

//Objective-C
NSData * nsdataObject = // Objeto NSData
[[WCSession defaultSession] sendMessageData:nsdataObject
                           replyHandler:^(NSDictionary *replyHandler) {
                           // Recibimos la respuesta
                           }
                           errorHandler:^(NSError *error) {
                             // Errores
                           }
];

Recibir mensajes

Para ambos envíos podemos usar dos tipos de recepción.

  • didReceiveMessage
  • didReceiveMessage replyHandler

El primero únicamente recibe el mensaje.

El segundo método recibe el mensaje pero además devuelve una respuesta.

didReceiveMessage

Para recibir el mensaje usaremos el siguiente código:

//Swift
func session(session: WCSession,
didReceiveMessage message: [String : AnyObject]){
}
//Objective-C
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message{
}

didReceiveMessage replyHandler

Si lo que queremos es que además de recibir un mensaje, recibamos una respuesta de la otra parte, usaremos este método.

//Swift
func session(session: WCSession, didReceiveMessage message: [String : AnyObject],
replyHandler: ([String : AnyObject]) -> Void){
}
//Objective-C
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary *)message
replyHandler:(void (^)(NSDictionary<NSString *,
id) *replyMessage))replyHandler{
}

Pues esto es todo. Te dejo un enlace a la documentación oficial de Apple.

Y ya sabes, si tienes alguna duda, o quieres decirme algo, déjame un comentario 😉

About The Author
iOS Developer & Instructor at CFE Apps. Enseño a crear aplicaciones iOS a todo el que quiera aprender.

2 Comments

  • Edgar 02/03/2016 @ 22:00

    Hola, que tal, me gustaría saber como puedo hacer que se muestren imágenes desde una url y se visualicen en el apple watch, se ven en el simulador, pero no en el reloj físico, ¿Alguna idea? gracias!

    • Sergio Becerril 03/03/2016 @ 13:41

      Hola Edgar,

      No puedo ayudarte con las indicaciones que me dices, te pueden estar pasando tantas cosas…

      Gracias por visitar el Blog y por comentar.

      Un abrazo.
      Sergio Becerril

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.