What communication to use, updateApplicationContext or sendMessage for constant data sync

Hi,


I have an iOS shopping list app, where items are added and displayed in a tableView. I want to create a Watch App Extension but I’m debating on what type of communication I need to use, the updateApplicationContext () methodor the sendMessage() method. I was reading the documentation but I’m a little confused since both seem to work.


Here is the functionality I’m expecting to have…


What I want is to be able to add items in the iOS app even if the Watch app is Off, which is normal behavior, BUT I want the Watch app to update with whatever is in the tableView (in iOS) as soon as it is turned on and even if the iPhone is not On at the time the Watch is turned on.


In other words, I want the data in the iOS app to always be in sync with the Watch app.


What is the best communication to use in this case, the

updateApplicationContext(_:)
method or the
sendMessage(_:replyHandler:errorHandler:)
method?


Thanks

Accepted Reply

I am using updateApplicationContext:(NSDictionary *)info very successfully. One trick was that the transmitted dictionary (i.e. info) must have a different key (not a different value) each time you want to send it. So I added a key that was a string of the current value of time with a value of @"anything".

Replies

I am using updateApplicationContext:(NSDictionary *)info very successfully. One trick was that the transmitted dictionary (i.e. info) must have a different key (not a different value) each time you want to send it. So I added a key that was a string of the current value of time with a value of @"anything".

I tried using updateApplicationContext and it seem to work using the same key everytime. I also noticed that the key must match in the counterpart.


The code below works fine, it updates the array in the watch everytime a new item is added.


Here is how I'm sending the data.


class ViewController: UIViewController, WCSessionDelegate {

    @IBOutlet weak var myField: UITextField!
    var session: WCSession!
    var fruits:[String] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        if WCSession.isSupported() {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
    }

     /// REQUIRED METHODS HERE..

    @IBAction func sendDataToWatch(_ sender: Any) {
        fruits.append(myField.text!)
        do {
            try WCSession.default().updateApplicationContext(["fruitsFromPhone": fruits])
        }
        catch {
            print(error)
        }
    }
}


Here is how I'm receiving the data:


class InterfaceController: WKInterfaceController, WCSessionDelegate {

    @IBOutlet var messageLabel: WKInterfaceLabel!
    var session: WCSession!

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        if (WCSession.isSupported()) {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
    }
    // REQUIRED METHOD HERE...

    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
        if let fruitsFromPhone = applicationContext["fruitsFromPhone"] as? [String]{
            print("\(fruitsFromPhone)")
            self.messageLabel.setText(messageFromPhone[0])
        }
    }
}

>it seem to work using the same key everytime

If you send a packet and then a few seconds later, without stopping the app, send either the same packet or a packet with different values but the same keys, does it send both teh first and the second packet? In my experience it did not. Therefore I had to add the random-key entry to assure that it would send the packet the second time. I also had to confirm receipt of the first packet before removing oitems I wanted to transmit.


Basically, in my experience, the system is designed to send one message for every execution of the app. If a second message is sent it before the first message has been delivered then the system cancels the delivery of the first message in preference for just sending the second message. If a first message is sent and delivered and then a second, same-keyed message is sent, it ignores the second message as redundant even if values are different.


So I send a package of information (a unique key/value and and key/array with each entry in the array being a dictionary) and respond back to the watch with the entries that were receieved. When I get that response back I delete those entries from the array. New data entries are added to the array and sent the enxt time with a unique key/value. That way if a second packet goes out before its predecessor has been delivered that's ok. And if a second packet goes out after its predecessor is delievered that's also ok. (This codes easier than it sounds.)