Search code examples
iosobjective-cwatchoswatchconnectivitywcsession

WCSession only working once


In my app, I have to send information from the watch InterfaceController to the phone HomeViewController. But, when I run my code, the information only works once. For it to work again, I have to delete the Apple Watch app and reinstall it.

InterfaceController.m:

#import "InterfaceController.h"
#import <WatchConnectivity/WatchConnectivity.h>

@interface InterfaceController() <WCSessionDelegate>

@property (strong, nonatomic) WCSession *session;

@end

@implementation InterfaceController

-(instancetype)init {
    self = [super init];

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

-(void)sendText:(NSString *)text {

    NSDictionary *applicationDict = @{@"text":text};
    [self.session updateApplicationContext:applicationDict error:nil];

}

- (IBAction)ButtonPressed {
    [self sendText:@"Hello World"];

}

HomeViewController.m:

#import "HomeViewController.h"
#import <WatchConnectivity/WatchConnectivity.h>

@interface HomeViewController ()<WCSessionDelegate>
@end

@implementation HomeViewController
@synthesize TextLabel;

- (void)viewDidLoad {
    [super viewDidLoad];

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

- (void)session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)applicationContext {

    NSString *text = [applicationContext objectForKey:@"text"];

    dispatch_async(dispatch_get_main_queue(), ^{
        [TextLabel setText:text];
    });
}

As mentioned, the iOS label only changes to "Hello World" once. After I relaunch the iOS app, and its text label no longer says "Hello World," I cannot manage to get the watch to change the iOS text label back to "Hello World" again.

Is this a problem with communication between the watch and the iPhone, or is it a problem with the code?


Solution

  • It's a problem with the code, based on the intent of updateApplicationContext:

    you should use this method to communicate state changes or to deliver data that is updated frequently

    In your case, you're trying to resend an unchanged application context from the watch to the phone.

    Since there is no change from the previous application context, and the phone won't receive anything different than what it previously received, there's no reason for the watch to (re)transmit anything, so it doesn't.

    This is an optimization that Apple designed into Watch Connectivity.

    How can you resolve this?

    • You could redesign your app to eliminate needing to retransmit the same data.

    • If your app must retransmit the same information a second time, you have to change your approach:

      • You can add additional data (such as a UUID or timestamp) to the application context, to ensure that the update you're sending is not identical to the previous application context you sent.

      • Use different WCSession functionality, such as sendMessage, which would let you resend identical data a second time.