11

I am developing a watchOS extension which uses WCSession to communicate with the iPhone. However, I do not own an Apple Watch and therefore have to rely on the Watch Simulator to test my code.

Is there a way to test the scenario where the Watch is disconnected from the phone in the Simulator?

If not, is there some documentation or a well-researched blog post that gives some insight into the behavior of WCSession in this case?

fabian789
  • 8,348
  • 4
  • 45
  • 91
  • 1
    This question is even relevant when you use real devices: as soon as you disconnect your iPhone, you're no longer able to debug anything on the Apple Watch. – Ely May 14 '19 at 19:28

6 Answers6

3

Quitting the iPhone simulator should let you approximate this scenario.

return true
  • 7,839
  • 2
  • 19
  • 35
ccjensen
  • 4,578
  • 2
  • 23
  • 25
  • Good idea! I am indeed unable to send data to the iPhone after quitting the simulator. However, `session.reachable` is still `true` on the watch and the error I get in the `errorHandler` of `sendMessage(...)` is `Code=7001 "Unknown WatchConnectivity error."` w/ the underlying error being `Code=23 "Timed out"`. Is this what you get on the watch when the iPhone is not in reach? – fabian789 Dec 26 '15 at 10:02
  • That is one possible error, but only if you hit a decently small race. The other more likely one is the not reachable error (I believe 7007). – ccjensen Dec 26 '15 at 10:05
  • Ok. According to `WCError.h`, it is indeed 7007. But so usually, `session.reachable` would be `false` when the iPhone disconnects? – fabian789 Dec 26 '15 at 10:08
  • 1
    That is correct. Best practices recommended by Apple is to use to check the session's reachability upon activation, and then from then on use the reachabilityDidChange delegate callback (or KVO) to be notified of changes to know when to check what reachability has been updated to. – ccjensen Dec 26 '15 at 11:07
2

I dont think so its possible because Apple doc says,

Additionally, WatchKit apps have a reliable connection to the simulated host device because they both are running in the Simulator.

Apple mentioned this in Hardware Difference section of Simulator User Guide

Nilesh Patel
  • 6,318
  • 1
  • 26
  • 40
  • Interesting link, thanks! However, in my opinion, this does not fully exclude the possibility that there is _some_ way to simulate my scenario! – fabian789 Dec 26 '15 at 10:05
1

You should use an if-query, whether the iPhone is reachable before starting a WC Request:

if (WCSession.defaultSession().reachable) {

   //do your request here

} else {

   //handle non-reachability

}

If you want to test your app's reaction on a non-reachability just replace WCSession.defaultSession().reachable with false.

fredpi
  • 8,414
  • 5
  • 41
  • 61
  • Thanks for the input, but I meant "test" in the sense of testing my code, not how to test for reachability _in_ code :) – fabian789 Dec 27 '15 at 16:53
1

I understand that you actually want a test scenario.

But which direction for communication do you want to test? If you check documentation of WCSession it always states the behavior for the watch and the iOS device.

Furthermore, what do you mean with 'disconnected'?

You can check for WCSession.defaultSession().reachable but documentation states

On iOS, the value is YES when the paired Apple Watch is in range and the associated Watch app is running in the foreground.

You can check for paired, but you also need to check for watchAppInstalled.

I believe that all communication is asynchronous. Do you want to check your errorHandler: code as in

- (void)sendMessageData:(NSData *)data
    replyHandler:(void (^)(NSData *replyMessageData))replyHandler
    errorHandler:(void (^)(NSError *error))errorHandler

I think it is not possible to test it on a simulator. You could only copy your errorHandler code temporarily to replyHandler for testing.

Here is the code I use for testing the availability:

if WCSession.isSupported() {
    let session = WCSession.defaultSession()
     session.delegate = _modelController
     session.activateSession()
    _modelController!.transferArrayToWatchWithSession()
}

and within the _modelController

func transferArrayToWatchWithSession() {
    let session = WCSession.defaultSession()
    if WCSession.isSupported() && session.watchAppInstalled {
        session.transferUserInfo([kWatchControlsDictKey:self.verifiedWatchArray])
    } else {
        log.info(....")
    }
}
theguy
  • 1,232
  • 1
  • 9
  • 21
  • I would like to test or "simulate" the real-world scenario where the iPhone is not close to the watch and see how the `WatchConnectivity` API behaves then. – fabian789 Jan 02 '16 at 11:55
0

Quit the iPhone simulator while the Apple Watch simulator is running achieves the specific state that you describe... As with an actual Apple Watch, the Watch Simulator will show a phone disconnected icon at the top of the screen when you quit the iPhone Simulator. See image below.

There is another state to consider, which is that WCSession only can communicate when the two apps are both in the foreground. Therefore, you should also test the scenario where the Watch and iPhone are connected (both simulators are running) but the iPhone app is not in the foreground. (And likewise, with the iPhone app in the foreground while the Watch is connected but the Watch app is not in the foreground.) Apple Watch Simulator with disconnected iPhone Simulator

Community
  • 1
  • 1
Duncan Babbage
  • 19,972
  • 4
  • 56
  • 93
  • Unfortunately this doesn’t seem to be working for me in Xcode 8. Additionally, the bit about the iPhone app in the background is incorrect; the iPhone app can be communicated with while it’s in the background, but not the watch app. – Jeff Kelley Aug 23 '16 at 19:06
0

You can simulate the isReachable going to be false by placing the app which is on foregroundState in a backgroundState by pressing one of those two buttons on the watch.
It has the same effect that the iPhone is two far from the watch to be connected ( out of range).
CF: https://developer.apple.com/documentation/watchconnectivity/wcsession/1615683-isreachable
Still today, there isn't a way to simulate the disconnect directly or i haven't find it, the isReachable still be true if your turn off the iPhone simulator in attend to simulate the disconnect.
Just place your function you would test in the sessionReachabilityDidChange(_ session: WCSession) of the delegate and assume it has the same effect.