2

Is it possible to use the WatchConnectivity framework when creating an independent watchOS app?

The documentation https://developer.apple.com/documentation/watchkit/creating_independent_watchos_apps states, that "An independent app can use WatchConnectivity to transfer information from its iOS companion app when the iOS device is available..."

But how do we send data between the iOS app and the watchOS app? The WCSession object always returns false when checking the isReachable property.

Thanks for the help :)

Renato Stauffer
  • 738
  • 2
  • 14
  • 30

1 Answers1

4

Before you can use WatchConnectivity, WCSession has to be activated on iOS as well as on watchOS (Apple suggests that you check first that the device supports WatchConnectivity).

Activation is done asynchronously. When finished, func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) is called in the delegate of the session object (which has to be set when the activation is initiated).
If activation was successful, the activationState is now .activated. Only then can any transfer be initiated.

There are several kinds of transfer. Some require .isReachable to be true, and some not.

updateApplicationContext(_:) sends a dictionary to the counterpart device. It will be received when the device is active. If this function is called multiple times before the counterpart device is active, only the last dictionary is received. This transfer does not require .isReachable.

transferUserInfo(_:) sends also a dictionary, but all dictionaries are delivered if the function is called multiple times. This transfer does also not require .isReachable.

sendMessage(_:replyHandler:errorHandler:) sends also a dictionary, and again all dictionaries are delivered if the function is called multiple times. This transfer does require .isReachable.
If replyHandler is specified, it must be ensured that it is actually available when the system tries to call it. (It can happen that the app calls this function, goes to background before the reply is sent, and is then terminated by the system. If the reply is then called, the thread will crash.).

There are other kinds of transfers for data, files, and complications, see the docs.

Now .isReachable is handled differently on iOS and watchOS.

iOS: .isReachable is true, if a paired and active watch is in range, the corresponding WatchKit extension is running, and the WatchKit extension’s .isReachable property is true.

watchOS: .isReachable is true, if the WatchKit extension is running in the foreground or is running with a high priority in the background, and the iOS device is within range. Please note that the iOS app is not required to be active. If the watch starts a transfer and the iOS app is not active, it is launched into background and can handle the communication.

You mentioned that .isReachable is always false.
So if this relates to the watchOS app, the reason may be that the activation of the WCSession was not finished successfully, or the iOS device is not within range.
If this relates to the iOS app, the reason may again be that the activation of the WCSession was not finished successfully, the watch app is not running in the foreground or is not running with a high priority in the background, or the watch is not in range.
Hope this helps a little!

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116
  • It is really strange, after calling session.activate() on WCSession.default i get the following error message: error reconnecting to daemon due to NSXPCConnectionInterrupted And the delegate method session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) is never called... Did you ever encounter this? – Renato Stauffer Feb 28 '20 at 09:43
  • Also the isCompanionAppInstalled property always returns false... – Renato Stauffer Feb 28 '20 at 10:12
  • The NSXPCConnectionInterrupted error is strange. It has been reported before [here](https://stackoverflow.com/q/41896818/1987726) for simulator and device, but without a solution. I assume you tried the usual things (clearing build folder and derived data, and rebooting simulators/devices, uninstall and reinstall the watch app, unpair and repair the watch). And I found [another post](https://stackoverflow.com/a/60031481/1987726) that addresses the `.isCompanionAppInstalled` problem. Maybe this helps you also? – Reinhard Männer Feb 28 '20 at 17:08