Apple Watch WCConnectionDelegate, sending message in activationDidComplete fails occasionally?

134 views Asked by At

I am having an issue where, when sending a message through WCConnection, the session.sendMessage fails sometimes if called in the delegate method activationDidCompleteWith. The issue is not repeatable every time (in fact, it works most of the time).

But forcing a session.sendMessage by using a button in my UI (calling the identical loading code) has a successful session communication immediately, so I know the issue is not in the session itself or the master app.

Is it unsafe to assume the session is ready to accept communication in activationDidCompleteWith? Is there a better place to be calling my initial communication?

1

There are 1 answers

1
Myk On BEST ANSWER

In my experience watch OS is pretty finicky, especially when using older model watches. That being said I think the answer to the question: "Is it unsafe to assume the session is ready to accept communication in activationDidCompleteWith?" is yes, it is unsafe to assume that.

In my own app I have a very similar case to yours and I solved it by sending a message until a response is received.

    // false until a response is received from the phone
    let receivedResponse: Bool = false 

    // function that sends the message
    func requestResponse() {
        guard WCSession.default.isReachable else {
            print("Phone not reachable")
            return
        }

        // callback that handles response
        let responseHandler: ([String: Any]) -> () = { response in
            receivedResponse = true
            callback(response)
        }

        WCSession.default.sendMessage(["Request": "Response"],
                                      replyHandler: responseHandler) { error in
            print(error.localizedDescription)
        }
    }

    // timer that calls the request function repeatedly
    let retryTimer = Timer.scheduledTimer(withTimeInterval: 1,
                                          repeats: true) { timer in
        if receivedResponse {
            // we know we got a response so clean up timer
            timer.invalidate()
        }
        requestResponse()
    }