5
votes

I'm working on an iOS app that must send updates to the Apple Watch app using a WCSession. It's working flawlesly in the iOS/Watch simulators, but not in real devices.

When I try to send a message with sendMessage:replyHandler:errorHandler: method, if the Apple Watch application is in background, I get the following error:

[WCSession _onqueue_notifyOfMessageError:messageID:withErrorHandler:] B322D88E-8F50-4BAB-86FF-AFD3B851E1CC errorHandler: NO with WCErrorCodeMessageReplyFailed -> WCErrorCodeNotReachable

But in my code I added all kinds of checks:

if (_session &&
    _session.isPaired &&
    _session.isWatchAppInstalled &&
    _session.isReachable &&
    _session.activationState == WCSessionActivationStateActivated)
{
    [_session sendMessage:dictionary 
             replyHandler:nil 
             errorHandler:^(NSError * _Nonnull error) {
                 NSLog(@"%@",error);
             }
    ];
}
else
{
    [_session transferUserInfo:dictionary];
}

Is there any reason why I could be getting a "Not Reachable" error message when sending the message, but session.isReachable returns true?

I've also handled the case where the session is not reachable, and I'm enqueuing the message with transferUserInfo: there, but since the session is detected as Reachable, the message is sent immediately and thus it's lost.

1

1 Answers

1
votes

Have you also written the error handler parameter of the sendMessage selector? In there you might as well check for the kind of error WCSession has raised while attempting to send the message, and in case you might as well also re-send the message data as ApplicationContext/UserInfo/FileTransfer depending on your app logic. I'd usually send the message data again as userInfo when I get these error codes: WCErrorCodeNotReachable, WCErrorCodeDeliveryFailed, WCErrorCodePayloadTooLarge, WCErrorCodeTransferTimedOut

Though in your case the sendMessage selector could be something like this:

if (YES == self.session.isReachable) {
    __weak typeof(self) weakSelf = self;
    [self.session sendMessage:dictionary 
    replyHandler:nil 
    errorHandler:^(NSError * _Nonnull error) {
        switch (error.code) {
            case WCErrorCodeNotReachable:
            case WCErrorCodeDeliveryFailed:
            case WCErrorCodePayloadTooLarge:
            case WCErrorCodeTransferTimedOut:
             [weakSelf.session sendUserInfo:dictionary];
            break;

            default:
                NSLog(@"Unrecoverable WCSession transfer error: %@", error);
            break;
        }
    }]; 
} else {
   [self.session sendUserInfo:dictionary];
}