I looked at examples in the WatchOS 2 By Tutorial book written by the RayWenderlich team, in particular in chapter 18. They all work well. In my own application, I am trying to send a button with a clock to launch a button in an iPhone application. Here is the corresponding Swift code from Watch and phone:
Clock:
// // InterfaceController.swift // Wasted Time Extension // // Created by Michael Rowe on 7/21/15. // Copyright ยฉ 2010-2015 Michael Rowe. All rights reserved. // import WatchKit import WatchConnectivity import Foundation class InterfaceController: WKInterfaceController,WCSessionDelegate { @IBOutlet var wasteLabel: WKInterfaceLabel! @IBOutlet var costLabel: WKInterfaceLabel! @IBOutlet var counter: WKInterfaceLabel! @IBOutlet var statusButton: WKInterfaceButton! // our watchconnective session var session : WCSession? override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) } override func willActivate() { // This method is called when watch view controller is about to be visible to user super.willActivate() if(WCSession.isSupported()){ session = WCSession.defaultSession() session!.delegate = self session!.activateSession() } } override func didDeactivate() { // This method is called when watch view controller is no longer visible super.didDeactivate() } func session(session: WCSession, didReceiveMessage message: [String: AnyObject], replyHandler: [String: AnyObject] -> Void) { print("Did receive message Watch \(message)") } @IBAction func addButtonPressed() { // Pull values from the Phone for current meeting cost, waste costs, and people in meeting let prefs:NSUserDefaults = NSUserDefaults(suiteName: "abc")! var counterd = prefs.doubleForKey("keyPeopleInMeeting") counterd++ counter.setText(String(format:"%9.0f", counterd)) // Sending data to iPhone via Interactive Messaging if WCSession.isSupported(){ // we have a watch supporting iPhone let session = WCSession.defaultSession() // we can reach the watch if session.reachable { let message = ["add": "1"] print("Message \(message)") session.transferUserInfo(message) print("Send Message Add - People \(counterd)") } } if WCSession.isSupported() { let session = WCSession.defaultSession() if session.reachable { let message = ["add":"1"] session.sendMessage(message, replyHandler: { ( reply: [String: AnyObject]) -> Void in print("Reply: \(reply)") }, errorHandler: { (error: NSError) -> Void in print("ERROR Watch: \(error.localizedDescription)") }) } else { // reachable self.showReachabilityError() } } print("Watch Add Button Pressed \(counterd)") } @IBAction func minusButtonPressed() { // Pull values from the Phone for current meeting cost, waste costs, and people in meeting let prefs:NSUserDefaults = NSUserDefaults(suiteName: "abc")! var counterd = prefs.doubleForKey("keyPeopleInMeeting") counterd-- if (counterd <= 1) { counterd = 1 } counter.setText(String(format:"%9.0f", counterd)) if WCSession.isSupported() { let session = WCSession.defaultSession() if session.reachable { let message = ["minus":"1"] session.sendMessage(message, replyHandler: { ( reply: [String: AnyObject]) -> Void in print("Reply: \(reply)") }, errorHandler: { (error: NSError) -> Void in print("ERROR Watch: \(error.localizedDescription)") }) } else { // reachable self.showReachabilityError() } } print("Watch Minus Button Pressed \(counterd)") } func statusButtonPressed() { // Pull values from the Phone for current meeting cost, waste costs, and people in meeting let prefs:NSUserDefaults = NSUserDefaults(suiteName: "abc")! let status = statusButton.description if WCSession.isSupported() { let session = WCSession.defaultSession() if session.reachable { let message = ["status":status] session.sendMessage(message, replyHandler: { ( reply: [String: AnyObject]) -> Void in print("Reply: \(reply)") }, errorHandler: { (error: NSError) -> Void in print("ERROR Watch: \(error.localizedDescription)") }) } else { // reachable self.showReachabilityError() } } print("Watch Status Button Pressed - Status \(statusButton)") } func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]){ let prefs:NSUserDefaults = NSUserDefaults(suiteName: "abc")! if let waste = applicationContext["waste"] as? Float { print("Watch Receive - Waste \(waste)") } if let cost = applicationContext["cost"] as? Float { print("Watch Receive - Cost \(cost)") } if let counternum = applicationContext["counter"] as? Float { print("Watch Receive - Counter \(counternum)") } if let status = applicationContext["status"] as? String { print("Watch Receive - Status \(status)") statusButton.setTitle(status) } } private func showReachabilityError() { let tryAgain = WKAlertAction(title: "Try Again", style: .Default, handler: { () -> Void in }) let cancel = WKAlertAction(title: "Cancel", style: .Cancel, handler: { () -> Void in }) self.presentAlertControllerWithTitle("Your iPhone is not reachable.", message: "You cannot adjust the status or number of attendees Watch is not currently connected to your iPhone. Please ensure your iPhone is on and within range of your Watch.", preferredStyle: WKAlertControllerStyle.Alert, actions:[tryAgain, cancel]) } func session(session: WCSession, didFinishUserInfoTransfer userInfoTransfer: WCSessionUserInfoTransfer, error: NSError?) { print("Transfer User Info Error watch: \(error)") } }
And the receiving code on the iPhone: CODE:
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { if let counterd = message["add"] as? Float { let reply = ["add":counterd] print("iPhone Receive Add \(counterd)") addButtonPressed(self) replyHandler(reply) } if let counterd = message["minus"] as? Float { let reply = ["minus":counterd] print("iPhone Receive minus \(counterd)") removeButtonPressed(self) replyHandler(reply) } if let status = message["status"] as? String { if status == "Start" { let reply = ["status":"Quorum"] meetingStartedButtonPressed(self) replyHandler(reply) } if status == "Quorum" { let reply = ["status": "Finish"] quorumButtonPressed(self) replyHandler(reply) } if status == "Finish" { let reply = ["status": "Reset"] meetingEndedButtonPressed(self) replyHandler(reply) } if status == "Reset" { let reply = ["status": "Start"] resetButtonPressed(self) replyHandler(reply) } print("iPhone Received Status Button \(status)") } }
I receive messages that work well on Watch, and I see them in the debug log ... But they do not work on the phone. The phone successfully sends its messages to the watch.
I tested this code both in the simulator and on my own watch and iPhone. Please note that messages from iPhone to Watch are performed using via updateApplicationContext and the message I am sending, which I am trying to use to send messages from watch phones to iPhone. Here's a sample iPhone code for sending context:
if WCSession.isSupported() { if session.watchAppInstalled { let UserInfo = ["waste":Float((wastedAmount.text! as NSString).floatValue), "cost":Float((totalAmount.text! as NSString).floatValue), "counter":Float((peopleInMeeting.text! as NSString).floatValue), "status":"Start"] do { try session.updateApplicationContext(UserInfo as! [String : AnyObject]) } catch { print("Updating the context failed: ") } } }