3

As I read the doc, transferUserInfo is a queued process of 1, and the latest data will surely reach the watch sandbox.

This is the code on the iOS app:

-(void)sendViaTransferUserInfo {
    NSDictionary *weatherData = [[NSDictionary alloc] initWithObjectsAndKeys:
                                     self.cityName, @"City",
                                     self.tempCelciusStr, @"Temp",
                                     nil];

    WCSession *session = [WCSession defaultSession];
    [session transferUserInfo:weatherData]; 
}

If the iOS app and the watch app are both active, this works all the time.

But when I close the watch app, then call this method again from the iOS app, wait a few seconds and then open the watch app again, the watch delegate didReceiveUserInfo: is not being triggered at all.

Do I correctly understand transferUserInfo: usage? Can anybody explain why the delegate is not being called on the watch app?

GeneCode
  • 7,545
  • 8
  • 50
  • 85

1 Answers1

3

As I read the doc, transferUserInfo is a queued process of 1,

No, its possible to queue multiple user info transfers, and each will be received in the order that it was delivered.

What you're describing is updateApplicationContext. Only one context can be queued, and the most recent context replaces any previously received one.

and the latest data will surely reach the watch sandbox.

No, transfers will only complete if the session is active. Transfers will fail with an error if the session is inactive.

This is why the delegate did not get called on the watch side, as your watch app did not receive any data. The transfer failed on the phone side before sending, and nothing actually was transferred to the watch.

How to resolve the issues:

  • Check the activationState before transferring any data. Only attempt to transfer data when the session is active.

    Check the value of this property before attempting to transfer data or files using the methods of this object. When the value is WCSessionActivationStateActivated you may initiate the transfer of data and files normally. If it is any other value, do not initiate any transfers.

  • Use session(_:didFinishUserInfoTransfer:error:) to determine if the transfer succeeded.

    The session object calls this method when a data transfer initiated by the current app finished, either successfully or unsuccessfully. Use this method to note that the transfer completed or to respond to errors, perhaps by trying to send the data again at a later time.

Community
  • 1
  • 1
  • Hm. My code checked for [session isReachable] I guess that's the problem. Checking for activationState did the trick. Thanks. – GeneCode Aug 22 '16 at 02:26
  • My conclusion is: isReachable should be used for instantaneous transfers (sendMsg,sendMsgData) and activationState for background transfers. Right? – GeneCode Aug 22 '16 at 02:29
  • 1
    All communication, immediate as well as background, requires the session to be active. Reachable is an *additional* requirement for immediate messaging. Per [the documentation](https://developer.apple.com/library/ios/documentation/WatchConnectivity/Reference/WCSession_class/#//apple_ref/occ/instp/WCSession/reachable), "[isReachable] is valid only for a configured session that has been activated successfully. If the activationState property is available, its value must be WCSessionActivationStateActivated. When the session becomes inactive or deactivated, you should ignore [isReachable]." –  Aug 22 '16 at 02:38