Dear Apple,
The main issue is that delegate method 'session:didReceiveFile:' on the Watch part is only called during the first session after rebooting the Watch.
It's never called again, even though 'session:didFinishFileTransfer:' is called without error on the iOS part, after using 'transferFile:'.
Our team is wondering whether we have implemented the new delegate methods incorrectly, or that there are more bugs.
We are using iOS 9.3.2 beta 1 and watchOS 2.2.1 beta 1.
Can you explain in detail what the 3 new mandatory delegate methods in watchOS 2.2 and iOS 9.3 do, and moreover, suggest what code should be used inside?
- (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error
- (void)sessionDidBecomeInactive:(WCSession *)session
- (void)sessionDidDeactivate:(WCSession *)session
Our current implementation
Before calling 'transferFile:' on iOS, we verify that a WCSession is activated and the watch is paired via this convenience method 'isPaired':
- (BOOL)isPaired {
if ([WCSession class]) {
if ([WCSession isSupported]) {
// For watchOS 2.2 and higher it's mandatory to check the value of property 'activationState':
if ([[WCSession defaultSession] respondsToSelector:@selector(activationState)]) {
NSLog(@"Property 'activationState' exists -> watchOS 2.2 or higher. Value = %ld", (long)[_watchSession activationState]);
// When not activated, return NO:
if ([_watchSession activationState] != WCSessionActivationStateActivated) {
return NO;
}
}
BOOL paired = _watchSession.paired;
CLS_LOG(@"AppDelegate: isPaired = %d", paired);
return paired;
}
}
return NO;
}
So 'transferFile:' will never be called when "activationState" is not WCSessionActivationStateActivated, according to your documentation.
Currently we only use 'activationDidCompleteWithState:' on the Watch part, since the other 2 methods are not part of WCSessionDelegate for watchOS (only on iOS).
It's used in singleton class ConnectivityManager, to start sending message data to the paired iPhone via WCSession 'sendMessage:replyHandler:errorHandler'. Method 'activationDidCompleteWithState:' is called async after calling 'activateSession' in the init of the singleton. This works flawless.
- (id)init {
if (self = [super init]) {
NSLog(@"ConnectivityManager: init");
// Activate Connectivity session with iPhone:
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
return self;
}
- (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error{
NSLog(@"ConnectivityManager: activationDidCompleteWithState: %d", activationState);
if (activationState == WCSessionActivationStateActivated) {
// Connect to phone:
[self connectToPhone];
}
}
}
Our iOS app acts upon requests from the Watch via 'session:didReceiveMessage:replyHandler:'. Any action on the iOS app that follows on a request is preceded by the above described method 'isPaired' to ensure that "activationState" equals WCSessionActivationStateActivated.
So basically we have implemented the 3 new delegate methodswithout functionality, except 'sessionDidDeactivate'. That's populated according to a previous response in this topic:
- (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error{
CLS_LOG(@"AppDelegate: activationDidCompleteWithState: %ld", (long)activationState);
}
- (void)sessionDidBecomeInactive:(WCSession *)session{
CLS_LOG(@"AppDelegate: sessionDidBecomeInactive:");
}
- (void)sessionDidDeactivate:(WCSession *)session {
CLS_LOG(@"AppDelegate: sessionDidDeactivate");
[_watchSession activateSession];
}
Please advice how we should change the code in order to have a 100% succes rate in seeing the delegate method 'session:didReceiveFile:' on the Watch part being called after using 'transferFile:' on the iOS app.
Thanks for your support,
Martijn