If I run the app on the simulators, everything works fine: messages are sent and received correctly on both the iPhone and the Watch. (You can find a reference gif on imgur.com/ + o1ZQTLp).
The problem occurs when I try to run the same apps on my physical devices. Session is activated successfully but messages aren't sent. If I debug the code, I even see the WCSession.isReachable value set to true.
When debugging the WatchKit app, I see errorHandler is called on the func sendMessage(), and the error states:
However, the errorHandler isn't called from the iPhone app.WatchConnectivity session on paired device is not reachable.
Details of my devices:
iOS version: 14.0.1
WatchOS version: 7.0.1
I tested this same code before installing the 7.0.1 WatchOS and it worked without any problems, so I wonder if the update introduced some error on the WatchConnectivity framework.
Code on the iPhone app:
Code Block Swift import UIKit import WatchConnectivity class ViewController: UIViewController { @IBOutlet weak var messageLabel: UILabel! fileprivate var wcSession: WCSession! override func viewDidLoad() { super.viewDidLoad() wcSession = WCSession.default wcSession.delegate = self wcSession.activate() } @IBAction func sendMessageAction(_ sender: Any) { let message = [ "content": "Message sent from iPhone on \(Date())." ] wcSession.sendMessage(message, replyHandler: nil, errorHandler: { error in print("Error when sending message: \(error.localizedDescription)") }) } } extension ViewController: WCSessionDelegate { func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { switch activationState { case .activated: print("WCSession activated successfully") case .inactive: print("Unable to activate the WCSession. Error: \(error?.localizedDescription ?? "--")") case .notActivated: print("Unexpected .notActivated state received after trying to activate the WCSession") @unknown default: print("Unexpected state received after trying to activate the WCSession") } } func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { guard let content = message["content"] as? String else { return } DispatchQueue.main.async { self.messageLabel.text = content } } func sessionDidBecomeInactive(_ session: WCSession) { } func sessionDidDeactivate(_ session: WCSession) { } }
Code on the Watch Kit app:
Code Block Swift import WatchKit import Foundation import WatchConnectivity class InterfaceController: WKInterfaceController { @IBOutlet weak var messageLabel: WKInterfaceLabel! fileprivate var wcSession: WCSession! override func awake(withContext context: Any?) { wcSession = WCSession.default wcSession.delegate = self wcSession.activate() } @IBAction func sendMessageAction() { let message = [ "content": "Message sent from Watch on \(Date())." ] wcSession.sendMessage(message, replyHandler: nil, errorHandler: { error in print("Error when sending message: \(error.localizedDescription)") }) } } extension InterfaceController: WCSessionDelegate { func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { switch activationState { case .activated: print("WCSession activated successfully") case .inactive: print("Unable to activate the WCSession. Error: \(error?.localizedDescription ?? "--")") case .notActivated: print("Unexpected .notActivated state received after trying to activate the WCSession") @unknown default: print("Unexpected state received after trying to activate the WCSession") } } func session(_ session: WCSession, didReceiveMessage message: [String: Any]) { guard let content = message["content"] as? String else { return } messageLabel.setText(content) } }