4

I have an iOS app that communicates with the paired watch using WatchConnectivity. In most cases, it works without problems, on the simulators and on the devices.

The problem:

During development on the simulators, I get now and then the following communication error when I try to send a direct message from iOS to watchOS using WCSession.default.sendMessage(_:replyHandler:errorHandler:):

Error Domain=WCErrorDomain Code=7007  
"WatchConnectivity session on paired device is not reachable."

I have read this related post, but it does not apply to my case, because my app does work normally.

My questions:

How can it be that the watch simulator becomes not reachable while the app is running on the iOS simulator?
Does it make sense just to retry sendMessage after a while?
Is there any workaround?

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116
  • There have been a bunch of problems with connectivity and the simulators in the betas. You may still be able to review the release notes to see them. I suspect you are seeing some of those problems remaining... Whether or not to retry is a good question. I would personally not do it based on the simulator behavior if you can test on hardware. – Cobra Dec 31 '18 at 14:06

1 Answers1

3

As a workaround, I modified the sendMessage function so that in case of this error the transfer is retried a number of times. Since then, all sendMessage transfers are executed successfully.

func sendMessage(_ message: [String: AnyObject],
                                 replyHandler: (([String: Any]) -> Void)?,
                                 errorHandler: ((Error) -> Void)?) {
    guard let communicationReadySession = communicationReadySession else {
        // watchOS: A session is always valid, so it will never come here.
        print("Cannot send direct message: No reachable session")
        let error = NSError.init(domain: kErrorDomainWatch, 
                                 code: kErrorCodeNoValidAndReachableSession, 
                                 userInfo: nil)
        errorHandler?(error)
        return
    }

    /* The following trySendingMessageToWatch sometimews fails with
    Error Domain=WCErrorDomain Code=7007 "WatchConnectivity session on paired device is not reachable."
    In this case, the transfer is retried a number of times.
    */
    let maxNrRetries = 5
    var availableRetries = maxNrRetries

    func trySendingMessageToWatch(_ message: [String: AnyObject]) {
        communicationReadySession.sendMessage(message, 
                                              replyHandler: replyHandler, 
                                              errorHandler: { error in
                                                              print("sending message to watch failed: error: \(error)")
                                                              let nsError = error as NSError
                                                              if nsError.domain == "WCErrorDomain" && nsError.code == 7007 && availableRetries > 0 {
                                                                 availableRetries = availableRetries - 1
                                                                 let randomDelay = Double.random(min: 0.3, max: 1.0)
                                                                 DispatchQueue.main.asyncAfter(deadline: .now() + randomDelay, execute: {
                                                                    trySendingMessageToWatch(message)
                                                                 })
                                                               } else {
                                                                 errorHandler?(error)
                                                               }
        })
    } // trySendingMessageToWatch

    trySendingMessageToWatch(message)
} // sendMessage
Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116
  • 2
    Used your solution in IOS15. Not sure why this sporadic isReachable message still occurs years later. – angryip Oct 15 '21 at 12:29