Send and receive messages from iPhone to Watch from multiple Controllers

301 views Asked by At

What is the proper way to handle communication sent and received from multiple controllers?

What I'm trying to do is send a message from two different viewControllers from iOS to two different interfaceControllers in WatchOS (separately, NOT at the sametime).

Here is what I have which only works for communication between ViewController2 and InterfaceController2, it crashes when a messages is sent from ViewController1 to InterfaceController1 since it appears to be targeting the session method from InterfaceController2 all the time.

ViewController 1:

class ViewController1: UIViewController,WCSessionDelegate{
    var session: WCSession!
    override func viewDidLoad() {
      super.viewDidLoad()
        if WCSession.isSupported() {
          session = WCSession.default()
          session.delegate = self
          session.activate()
        }
     }

      func sendDataToWatch(){
        let sendPrice:[String: Double] = ["price": 3.99]
        session.sendMessage(sendPrice, replyHandler: { replyMessage in
            // Some reply here, this could be nil
        }, errorHandler: {error in
            // Catch any errors here, this could be nil
            print("Error: \(error.localizedDescription)")
        })
     }
}

InterfaceController 1: Receives message form ViewController 1

class InterfaceController1: WKInterfaceController, WCSessionDelegate{
   var session: WCSession!

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

        if (WCSession.isSupported()) {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
    }

   func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {

    /// Capture data from ViewContorller 2
    let priceFromPhone = message["price"] as? String

    // do something with priceFromPhone
   } 
}

// ===========================================

ViewController 2:

class ViewController2: UIViewController,WCSessionDelegate{
    var session: WCSession!
    override func viewDidLoad() {
      super.viewDidLoad()
        if WCSession.isSupported() {
          session = WCSession.default()
          session.delegate = self
          session.activate()
        }
     }

   func sendDataToWatch(){
    let sendEngine:[String: Double] = ["engine": 2.5]
    session.sendMessage(sendEngine, replyHandler: { replyMessage in
        // Some reply here, this could be nil
    }, errorHandler: {error in
        // Catch any errors here, this could be nil
        print("Error: \(error.localizedDescription)")
    })
  }
}

InterfaceController 2: Receives message from ViewController 2

class InterfaceController2: WKInterfaceController, WCSessionDelegate{
   var session: WCSession!

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

        if (WCSession.isSupported()) {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
    }

   func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {

      /// Capture data from ViewContorller 2
      let engineFromPhone = message["engine"] as? String

      // do something with engineFromPhone
    }    
 }

Thanks

2

There are 2 answers

3
ccjensen On BEST ANSWER

I'd suggest removing all data management away from the controllers that handle your UI. It is a poor design and will likely cause you headaches later to mix the layers like this.

You should instead have a data manager that is the WCSession delegate and takes care of persisting the information, and then notifying the relevant parties (view controllers, etc) that the backing data has been updated.

0
fs_tigre On

Based on what I have read, it looks like I will need to narrow down the communication to only one ViewController and one InterfaceController and then share the changes via NSNotification or Delegation.

WatchConnectivity how to share session among multiple WKInterfaceControllers?

Using WCSession with more than one ViewController