Il passaggio di dati per Apple Watch app

Sto cercando di passare i dati dalla mia app nella mia Watch Apple app. Fondamentalmente, sto usando lo stesso metodo che ho usato per la creazione di oggi widget e così io sono il passaggio di dati attraverso NSUserDefaults.

Il problema è che quando eseguo la mia app, i dati non aggiorna le etichette in applicazione Watch come mi aspetterei che.

Qui è che cosa ho…

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)")
    }
}

Ho provato a mettere questo codice in willActivate(), tuttavia, che non sembra fare la differenza.

Qualcuno sa dove sto andando male?

InformationsquelleAutor user3746428 | 2014-11-19



4 Replies
  1. 25

    Ho capito di lavoro usando il tuo metodo. Credo che ci sono un paio di cose che si possono controllare:

    1) siete a sincronizzare le impostazioni predefinite dopo aver impostato il valore:

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

    2) hai attivato l’App di Gruppo, sia l’applicazione e l’estensione?

    Il passaggio di dati per Apple Watch app
    Il passaggio di dati per Apple Watch app

    3) stai usando correttamente app di gruppo per la costruzione del NSDefaults? Per esempio, io uso:

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

    Una volta che tutto è impostato, ho eseguito l’applicazione, impostare il valore di default, quindi eseguire il colpo d’occhio di destinazione in cui si legge il valore di default e che sembra funzionare!

    Il passaggio di dati per Apple Watch app

    1. Ancora bloccato? controlla la tua app gruppi nel tuo account apple
    • Grande! Grazie mille. Il problema era che io non avevo impostare l’App di Gruppo per l’Orologio.
    • Sarebbe questo anche per Watch<–>Orologio di comunicazione?
    • Ho seguito la stessa procedura, ma non funziona per me. Io sono sempre nil dati . Qualsiasi debug di aiuto..
    • Ho fatto la stessa cosa e anche io sto ricevendo nil dati. È questo un problema con il simulatore?
    • questa opzione non funziona su OS2
  2. 23

    Accettato risposta vale per apple watch os 1. Vedere NSUserDefaults non funziona su Xcode beta con l’Orologio OS2

    Per OS2 – sarà necessario utilizzare il WatchConnectivity quadri e implementare la 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")
    
            }
        }
    
    }

    Esempio Di Utilizzo

    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)
        }
    
    }

    Il passaggio di dati per Apple Watch app

    nel mio iphone codice /I può invocare la condivisione dei dati qui

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

    E da qualche altra parte ho un altro discreto singleton per guardare i dati di sessione.

    @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.paired){
                if(session.watchAppInstalled){
                    print("paired | watchAppInstalled")
                }
            }else{
               print("not paired | 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)
                })
    
            }
    
        }
    
    }

    Vedere campioni guardare os2 app

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

    • C’è un codice di esempio che utilizza applicationContext() su github vedi: github.com/JohnGoodstadt/applicationContext
    • è normale che quando si invia un messaggio da telefono per guardare se non è raggiungibile non consegnare il messaggio e non riprovare più tardi, ma da guardare per telefono, se non è raggiungibile è di attendere fino a quando non è raggiungibile e il messaggio, infine, è stato consegnato?
  3. 18

    Come @johndpope detto, condiviso NSUserDefaults non lavoro più WatchOS2.

    Sto postando una soluzione semplificata che non è così completo come giovanni, ma otterrà il lavoro fatto nella maggior parte dei casi.

    Nel vostro iPhone App, attenersi alla seguente procedura:

    Pick trovare il controller di visualizzazione che si desidera inserire i dati per l’Apple Watch e aggiungere il quadro in alto.

    import WatchConnectivity

    Ora, stabilire un WatchConnectivity sessione con l’orologio e l’invio di dati.

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

    Si prega di notare, questo NON funzionerà se si ignora l’impostazione del delegato, quindi, anche se non la uso mai, è necessario impostare e aggiungere questa estensione:

    extension MyViewController: WCSessionDelegate {
    
    }

    Ora, nella tua applicazione watch (questo codice esatto opere di Sguardi e di orologi altri kit tipi di app così) si aggiunge il quadro:

    import WatchConnectivity

    Quindi si imposta la connettività sessione:

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

    e semplicemente ascoltare e gestire i messaggi da iOS app:

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

    Che è tutto là è ad esso.

    Elementi di nota:

    1. È possibile inviare un nuovo applicationContext come spesso come ti piace e la si
      non importa se l’orologio è vicino e collegato o se l’orologio
      l’app è in esecuzione. Questo fornisce i dati in background in un
      modo intelligente e che i dati è seduto lì in attesa, quando il
      guarda app viene lanciata.
    2. Se il vostro orologio app è effettivamente attivo e in esecuzione, si dovrebbe ricevere
      il messaggio immediatamente nella maggior parte dei casi.
    3. È possibile invertire questo codice per avere l’orologio inviare messaggi a
      app per iPhone allo stesso modo.
    4. applicationContext che il vostro orologio app riceve quando viene visualizzato SOLO l’ultimo messaggio che hai inviato. Se hai 20 messaggi di prima applicazione watch è visto, ignorerà i primi 19 e gestire le 20 una.
    5. Per fare una diretta/rigido collegamento tra le 2 applicazioni o per trasferimenti di file in background o in coda messaggi, controllare il WWDC video.
    • Grazie! Questo è stato fantastico.
  4. 6

    Un altro modo di comunicare tra le app e l’orologio via wormhole:

    https://github.com/mutualmobile/MMWormhole

    Inviare:

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

    Ricevere:

    [self.wormhole listenForMessageWithIdentifier:@"messageIdentifier" 
    listener:^(id messageObject) {
    //Do Something
    }];
    • Avete provato questo metodo? È affidabile?
    • Reciproco mobile è un esempio di build che ho eseguito, che ha effettivamente trasmettere i dati da iPhone a guardare
    • MMWormhole utilizza solo il basso livello di Darwin sistema di notifica che è stato intorno per un bel po ‘ di tempo, hanno appena costruito un involucro intorno ad esso. Infatti, ho visto questo metodo raccomandato dagli ingegneri Apple. Direi che è abbastanza affidabile.
    • per os 2 – utilizzare apple WatchConnectivity quadri.
    • lo fa solo lavorare su OS2? Sembra watchConnectivity non è disponibile come quadro, e io sono il targeting per ios8.2+
    • Se la destinazione di ios 8.2, si dovrebbe essere in grado di utilizzare l’esempio fornito. Utilizzare la versione 1.2.0 quindi non c’è bisogno watchConnectivity. Aggiungi questo al tuo podfile: pod ‘MMWormhole’, ‘~> 1.2.0’ La versione 2.0 di MMWormhole è stato aggiornato per supportare il WatchConnectivity quadro. La documentazione è disponibile qui: MMWormholeSession
    • MMWormhole è molto utile, funziona per guardare OS 2 anche le api. Ma mi trovo di fronte a problemi durante il trasferimento di classe personalizzata oggetti da iPhone a guardare. Ma funziona meglio per il trasferimento di oggetti semplici come stringhe e dizionari.
    • Anche io sono di fronte a stesso problema con un oggetto personalizzato. Hai trovato qualche soluzione per questo ?
    • Puoi provare a serializzare gli oggetti di classe il modo ObjectMapper fa. In realtà si può utilizzare lo stesso ObjectMapper.

Lascia un commento