Pasar datos a la aplicación Apple Watch

Estoy tratando de pasar datos de mi aplicación a mi aplicación Apple Watch. Básicamente, estoy usando el mismo método que utilicé para crear el widget de hoy, así que estoy pasando datos a través de NSUserDefaults.

El problema es que cuando ejecuto mi aplicación, los datos no actualizan las tags en la aplicación Watch como esperaría.

Esto es lo que tengo …

override init(context: AnyObject?) { // Initialize variables here. super.init(context: context) // Configure interface objects here. NSLog("%@ init", self) var defaults = NSUserDefaults(suiteName: "group.AffordIt") var totalBudgetCalculation = "" if (defaults!.stringForKey("totalBudgetWidget") != nil) { println("Worked") totalBudgetCalculation = defaults!.stringForKey("totalBudgetWidget")! initialBudgetLabel.setText("Initial: \(totalBudgetCalculation)") } var currentBudgetCalculation = "" if (defaults!.stringForKey("currentBudgetWidget") != nil) { currentBudgetCalculation = defaults!.stringForKey("currentBudgetWidget")! currentBudgetLabel.setText("Current: \(currentBudgetCalculation)") } } 

Intenté poner este código en willActivate() , sin embargo, eso no parece marcar la diferencia.

¿Alguien sabe dónde me estoy equivocando?

    Lo hice funcionar usando tu método. Supongo que hay un par de cosas que puedes verificar:

    1) ¿Está sincronizando los valores predeterminados después de establecer el valor?

     defaults?.synchronize(); NSLog("%@ ", defaults?.dictionaryRepresentation()) 

    2) ¿Ha habilitado el grupo de aplicaciones en su aplicación y su extensión?

    Capacidad del grupo de aplicaciones para el objetivo de la aplicaciónCapacidad del grupo de aplicaciones para ver el objetivo de extensión

    3) ¿Estás utilizando el grupo de aplicaciones correctamente nombrado al construir los NSDefaults? Por ejemplo, yo uso:

     NSUserDefaults(suiteName: "group.com.brindysoft.MyWatch"); 

    Una vez que todo está configurado, ejecuto la aplicación, establezco el valor en los valores predeterminados, luego ejecuto el objective de vistazo que lee el valor del valor predeterminado y parece funcionar.

    enter image description here

    1. ¿Todavía estancado? revisa tus grupos de aplicaciones en tu cuenta de Apple

    La respuesta aceptada se aplica a apple watch os 1. Ver NSUserDefaults no funciona en Xcode beta con Watch OS2

    Para OS2: deberá usar los marcos de WatchConnectivity e implementar WCSessionDelegate.

     import WatchConnectivity import WatchKit @available(iOS 9.0, *) var alertDelegate:HomeIC? = nil public class WatchData: NSObject,WCSessionDelegate { var session = WCSession.defaultSession() // class var shared: WatchData { struct Static { static var onceToken: dispatch_once_t = 0 static var instance: WatchData? = nil } dispatch_once(&Static.onceToken) { Static.instance = WatchData() } return Static.instance! } public func session(session: WCSession, didReceiveFile file: WCSessionFile){ print(__FUNCTION__) print(session) } public func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) { print(__FUNCTION__) print(session) alertDelegate?.showMessage("didReceiveApplicationContext") } public func sessionReachabilityDidChange(session: WCSession){ print(__FUNCTION__) print(session) print("reachability changed:\(session.reachable)") let text = session.reachable ? "reachable" : "unreachable" alertDelegate?.showMessage(text) } public func sessionWatchStateDidChange(session: WCSession) { print(__FUNCTION__) print(session) print("reachable:\(session.reachable)") // alertDelegate?.showMessage("sessionWatchStateDidChange") if !session.receivedApplicationContext.keys.isEmpty { alertDelegate?.showMessage(session.receivedApplicationContext.description) } } public func session(session: WCSession, didReceiveMessageData messageData: NSData){ if !session.receivedApplicationContext.keys.isEmpty { alertDelegate?.showMessage(session.receivedApplicationContext.description) } } public func session(session: WCSession, didReceiveMessage message: [String : AnyObject]){ print(__FUNCTION__) if let data = message["data"] { alertDelegate?.showMessage(data as! String) return } } public func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { print(__FUNCTION__) if let data = message["data"] { alertDelegate?.showMessage(data as! String) return } guard message["request"] as? String == "showAlert" else {return} } public func activate(){ if WCSession.isSupported() { // it is supported session = WCSession.defaultSession() session.delegate = self session.activateSession() print("watch activating WCSession") } else { print("watch does not support WCSession") } if(!session.reachable){ print("not reachable") return }else{ print("watch is reachable") } } } 

    Uso de la muestra

     class HomeIC: WKInterfaceController { // MARK: Properties override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) // Initialize the `WCSession`. WatchData.shared.activate() alertDelegate = self } internal func showMessage(msg:String){ let defaultAction = WKAlertAction(title: msg, style: WKAlertActionStyle.Default) { () -> Void in } let actions = [defaultAction] self.presentAlertControllerWithTitle( "Info", message: "", preferredStyle: WKAlertControllerStyle.Alert, actions: actions) } } 

    enter image description here

    en mi código de iphone / puedo invocar compartir datos aquí

      if #available(iOS 9.0, *) { WatchData.shared.sendInbox() } else { // Fallback on earlier versions } 

    Y en otro lugar tengo otro singleton discreto para ver la sesión de datos.

     @available(iOS 9.0, *) public class WatchData: NSObject,WCSessionDelegate { var session = WCSession.defaultSession() var payload:String = "" class var shared: WatchData { struct Static { static var onceToken: dispatch_once_t = 0 static var instance: WatchData? = nil } dispatch_once(&Static.onceToken) { Static.instance = WatchData() } return Static.instance! } public func sessionReachabilityDidChange(session: WCSession){ print(__FUNCTION__) print(session) print("reachability changed:\(session.reachable)") if (session.reachable){ } } public func sessionWatchStateDidChange(session: WCSession) { print(__FUNCTION__) print(session) print("reachable:\(session.reachable)") } public func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { print(__FUNCTION__) guard message["request"] as? String == "showAlert" else {return} guard let m = message["m"] as? String else { return } print("msg:",m) } public func sendInbox(){ if (!session.reachable){ if WCSession.isSupported() { // it is supported session = WCSession.defaultSession() session.delegate = self session.activateSession() print("iphone activating WCSession") } else { print("iphone does not support WCSession") } session.activateSession() } if(session.paird){ if(session.watchAppInstalled){ print("paird | watchAppInstalled") } }else{ print("not paird | or no watchAppInstalled") } if(!session.reachable){ print("not reachable") return }else{ /*let transfer:WCSessionUserInfoTransfer = (session.transferUserInfo(["data" : "Test2"]) as WCSessionUserInfoTransfer?)! if(transfer.transferring){ print("-> iphone") }else{ print("!-> iphone") }*/ session.sendMessage(["data" :"test"], replyHandler: { reply in }, errorHandler: { error in print(error) }) } } } 

    Refiérase a la aplicación sample watch os2

    https://github.com/shu223/watchOS-2-Sampler/tree/20eeebeed66764d0814603e97d3aca5933236299

    Como dijo @johndpope, NSUserDefaults compartidos ya no funcionan en WatchOS2.

    Estoy publicando una solución simplificada que no está tan completa como la de John, pero hará el trabajo en la mayoría de los casos.

    En tu aplicación de iPhone , sigue estos pasos:

    Elija encontrar el controlador de vista desde el que desea insertar los datos en Apple Watch y agregue el marco en la parte superior.

     import WatchConnectivity 

    Ahora, establezca una sesión WatchConnectivity con el reloj y envíe algunos datos.

     if WCSession.isSupported() { //makes sure it's not an iPad or iPod let watchSession = WCSession.defaultSession() watchSession.delegate = self watchSession.activateSession() if watchSession.paird && watchSession.watchAppInstalled { do { try watchSession.updateApplicationContext(["foo": "bar"]) } catch let error as NSError { print(error.description) } } } 

    Tenga en cuenta que esto NO funcionará si omite configurar el delegado, por lo que incluso si nunca lo usa, debe configurarlo y agregar esta extensión:

     extension MyViewController: WCSessionDelegate { } 

    Ahora, en su aplicación de reloj (este código exacto también funciona para Glances y otros tipos de aplicaciones de kits de vigilancia), agrega el marco:

     import WatchConnectivity 

    Luego configura la sesión de conectividad:

     override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) let watchSession = WCSession.defaultSession() watchSession.delegate = self watchSession.activateSession() } 

    y simplemente escucha y maneja los mensajes de la aplicación de iOS:

     extension InterfaceController: WCSessionDelegate { func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) { print("\(applicationContext)") dispatch_async(dispatch_get_main_queue(), { //update UI here }) } } 

    Eso es todo al respecto.

    Elementos de la nota:

    1. Puede enviar un nuevo ApplicationContext tantas veces como desee y no importa si el reloj está cerca y conectado o si la aplicación de visualización se está ejecutando. Esto entrega los datos en segundo plano de una manera inteligente y esa información está esperando allí cuando se inicia la aplicación de vigilancia.
    2. Si su aplicación de vigilancia está realmente activa y ejecutándose, debería recibir el mensaje de inmediato en la mayoría de los casos.
    3. Puede revertir este código para que el reloj envíe mensajes a la aplicación de iPhone de la misma manera.
    4. applicationContext que su aplicación de reloj recibe cuando se lo visualiza SOLO será el último mensaje enviado. Si envió 20 mensajes antes de ver la aplicación de observación, ignorará los primeros 19 y se encargará de la vigésima.
    5. Para hacer una conexión directa / difícil entre las 2 aplicaciones o para transferencias de archivos en segundo plano o mensajes en cola, consulte el video WWDC .

    Otra forma de comunicarse entre la aplicación y el reloj es a través del agujero de gusano:

    https://github.com/mutualmobile/MMWormhole

    Enviar:

     [self.wormhole passMessageObject:@{@"titleString" : title} identifier:@"messageIdentifier"]; id messageObject = [self.wormhole messageWithIdentifier:@"messageIdentifier"]; 

    Recibir:

     [self.wormhole listenForMessageWithIdentifier:@"messageIdentifier" listener:^(id messageObject) { // Do Something }];