1

I have read the q/a below, and it's great. This is exactly what I'm doing in a test project, and it works fine.

I've now created my real project, but in the Watch extension, session: didReceiveApplicationContext: does not fire.

Here is my send code:

-(void)sendPlistToWatch:(NSMutableDictionary *)dictionary {
    NSLog(@"%s", __FUNCTION__);
    if ([WCSession defaultSession]) {
        NSDictionary *applicationDict = @{@"Favorites.plist":dictionary};
        [[WCSession defaultSession] updateApplicationContext:applicationDict error:nil];

        NSLog(@"sent dictionary");
    } else {
        NSLog(@"not paired");
    }
}

And this is the receive code on the watch:

- (void)awakeWithContext:(id)context {
    [super awakeWithContext:context];

    if ([WCSession isSupported]) {
        [self.session activateSession];
        self.session = [WCSession defaultSession];
        self.session.delegate = self;
    }
}

- (void)willActivate {
    [super willActivate];
}

- (void)didDeactivate {
    [super didDeactivate];
}



- (void)session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)applicationContext {
    NSString *string = [applicationContext objectForKey:@"dictionary"];

    NSMutableDictionary *dictionary = [applicationContext objectForKey:@"dictionary"];

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog (@"applicationContext: %@", applicationContext);
    });

}

Send messages between iOS and WatchOS with WatchConnectivity in watchOS2

I've watched the WWDC connectivity session, and find this site very helpful.

Any ideas (perhaps it's not code, but a missing or incorrect plist setting?)

Community
  • 1
  • 1
ICL1901
  • 7,632
  • 14
  • 90
  • 138

2 Answers2

6

I've run into a similar issue (iOS 9.3, watchOS 2.2) where the session: didReceiveApplicationContext: delegate method wouldn't fire when expected. It appears there's some undocumented behavior whereby if the dictionary matches the previous value sent, the call to updateApplicationContext() fails silently, neither sending the dictionary nor throwing an error (see https://forums.developer.apple.com/thread/46107).

The solution offered in that thread was to add a NSUUID().UUIDString to every dictionary while testing. Worked for me.

khaullen
  • 337
  • 6
  • 7
  • I think they purposely do that to preserve watch battery. If values and objects are the same, there is no point to send anyways using applicationcontext. You might want to reconsider using other methods since applicationcontext's purpose is to update watch app states primarily. – GeneCode Aug 23 '16 at 07:41
  • Does this occur only on simulators? or on actual devices too? – Zaira Zafar Feb 23 '18 at 06:32
  • Tested only on the simulator, cannot confirm whether this is also an issue on real devices. – khaullen Feb 23 '18 at 18:40
2

Found the cause...

I did activate the session, but it was too late in the process to be called.

I changed the code to report an error:

-(void)sendPlistToWatch:(NSMutableDictionary *)dictionary {
    NSLog(@"%s", __FUNCTION__);
    NSError *error = nil;
    if ([WCSession defaultSession]) {
        NSDictionary *applicationDict = @{@"StationFavorites.plist":dictionary};
        [[WCSession defaultSession] updateApplicationContext:applicationDict error:&error];
        if (error) {
             NSLog(@"Problem: @%@", error);
        } else {
             NSLog(@"sent dictionary");
        }

    } else {
        NSLog(@"not paired");
    }
}

That reported error 7004: WCErrorDomain Code=7004The operation couldn’t be completed. (WCErrorDomain error 7004.)"`

I reset the session to appear atop ViewDidLoad and all is well.

ICL1901
  • 7,632
  • 14
  • 90
  • 138