Today we are going to have a watchOS2 Tutorial in which we will learn how to transfer data & files between watchOS and Objective-C. watchOS 2 was a major release with lots of API level changes to help developers. watchOS 2 provides us with WatchConnectivity Framework, which we will focus on in this watchOS2 Tutorial.
- To start with, create a Single Screen iPhone Application in XCode and name it as WatchOS2Demo. Add WatchConnectivity Framework from Target -> Build Phases -> Link Binary With Libraries.
- To work on the Watch app we need to create a new Extension for it. Click on the “File” button next to XCode on the top bar, now a drop-down will appear choose “New” and select “Target”.
- A window will pop in saying to choose a template for the target. Select the Application under watchOS on the left side panel, on the right side you will see 2 options WatchKit App and WatchKit App for watchOS 1. As I am going to watch OS 2 demo so we will choose the 1st option WatchKit App which supports watchOS 2 and above. (Refer to the screenshot below):
- On hitting the Next button XCode will ask you if you want to Activate the Target – Choose YES.
- XCode will generate watch extension template files (InterfaceController h/m, ExtensionDelegate h/m, Interface. Storyboard, etc.).
Watch Extension Part:
In WatchKit Extension’s InterfaceController & iPhone App ViewController header files import the WatchConnectivity framework and also confirm to WCSessionDelegate protocol.
In WatchKit Extension’s InterfaceController implementation file check for:
- (void)awakeWithContext:(id)context In this method check if the WCSession is supported and if so activate it.
– (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
}
iPhone App Part:
In ViewController implementation file add the same code inside the – (void)viewDidLoad method.
– (void)viewDidLoad {
[super viewDidLoad];
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
}
WCSession can be used to transfer NSDictionary (applicationContext), NSData (message data), NSUrl (file) and provides the delegates for the same.
Below are the WCSession delegates to send information:
– (BOOL)updateApplicationContext:(NSDictionary<NSString *, id> *)applicationContext error:(NSError **)error;
- (WCSessionFileTransfer *)transferFile:(NSURL *)file metadata:(nullable NSDictionary<NSString *, id> *)metadata;
- (void)sendMessage:(NSDictionary<NSString *, id> *)message replyHandler:(nullable void (^)(NSDictionary<NSString *, id> *replyMessage))replyHandler errorHandler:(nullable void (^)(NSError *error))errorHandler;
– (void)sendMessageData:(NSData *)data replyHandler:(nullable void (^)(NSData *replyMessageData))replyHandler errorHandler:(nullable void (^)(NSError *error))errorHandler;
Below are the WCSession delegates to receive information:
- (void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary<NSString *, id> *)applicationContext;
- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file;- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void(^)(NSDictionary<NSString *, id> *replyMessage))replyHandler;
- (void)session:(WCSession *)session didReceiveMessageData:(NSData *)messageData;
Passing data via application context from iPhone to Watch:
To pass data from iPhone open the ViewController implementation file in iPhone App.
Add a UIButton with Title ‘Pass Data’ on the storyboard and set IBAction ‘– (IBAction)passAppContext:(id)sender;’ to it. Now let’s pass the NSDictionary to watch on hitting this button.
- (IBAction)passAppContext:(id)sender {
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
if ([session isPaired]) { // isPaired returns YES if the Watch is paired with iPhone (does not support the other way, so cannot be used in watch extension)
NSDictionary *applicationDict = @{@”kDeviceName”:@”iPhone”, @”kDeviceOSVersion”:@”iOS 9.3″};
NSError *error = nil;
[session updateApplicationContext:applicationDict error:&error];
if (error) {
NSLog(@”Unable to send Dictionary to Watch with error: %@”,error.localizedDescription);
}
} else {
NSLog(@”iPhone is not paired with Watch”);
}
} else {
NSLog(@”WCSession is not supported with this OS version.”);
}
}
Passing data via application context to Watch from iPhone:
To receive the data from iPhone to Watch open the InterfaceController implementation file in the Watch Extension.
Add the delegate method of WCSession to receive the applicationContext.
– (void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary<NSString *, id> *)applicationContext {
if (applicationContext != nil) {
NSString *dataReceivedfromiPhone = [NSString stringWithFormat:@”Device Name: %@, Device Version: %@”, [applicationContext objectForKey:@”kDeviceName”], [applicationContext objectForKey:@”kDeviceOSVersion”]];
WKAlertAction *action = [WKAlertAction actionWithTitle:@”OK” style:WKAlertActionStyleDefault handler:^{}];
NSString *title = @”Data Received”;
NSString *message = dataReceivedfromiPhone;
[self presentAlertControllerWithTitle:title message:message preferredStyle:WKAlertControllerStyleAlert actions:@[ action ]];
} else {
NSLog(@”Login failed on iPhone App”);
WKAlertAction *action = [WKAlertAction actionWithTitle:@”OK” style:WKAlertActionStyleDefault handler:^{}];
NSString *title = @”Oops!”;
NSString *message = @”iPhone App failed to login.”;
[self presentAlertControllerWithTitle:title message:message preferredStyle:WKAlertControllerStyleAlert actions:@[ action ]];
}
}
In the same way, we can send data from watchOS to iOS using Objective-C. In a similar fashion, you can implement the other delegates to communicate and transfer data and files between iOS and watchOS.
Read More: SAGE 100 VS SAGE X3: A MEANINGFUL UPGRADE?