How to Send Data from iPhone to Watchkit in Os2 in Swift

How to send data from Iphone to Watchkit in OS2 in SWIFT

This blog post should help you out.

From that post: First, you'll create and activate a WCSession like so:

if (WCSession.isSupported()) {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}

For transferring a dictionary:

let applicationDict = // Create a dict of application data
let transfer = WCSession.defaultSession().transferUserInfo(applicationDict)

Then, on the receiving end, you'll need to implement session:didReceiveUserInfo: (Developer documentation). Note, according to Apple's "watchOS2 Transition Guide,"

To begin communication, both your Watch app and your iOS app must have an active WCSession object. Typically, each app creates, configures, and activates a session object at launch time and stores a reference to it in a central location. When you want to send data, you retrieve the session object and call its methods.

How to send data from Iphone to Apple Watch in OS2 in Objective-C


Here´s a link to a Q/A about WatchConnectivity: Send messages between iOS and WatchOS with WatchConnectivity in watchOS2


I will give you an example go ApplicationContext, there are 2 other messaging techniques with WatchConnectivity. Please watch WWDC2015 session video for those.

First you need to conform to the WCSessionDelegate protocol in the classes you want to send and receive data from/to. E.g both on watch and iPhone.

Basic checking before: (this is just an example, implement better than this)

if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
NSLog(@"SESSION AVAIBLE");
}

//Objective-C
if ([[WCSession defaultSession] isReachable]) {
NSLog(@"SESSION REACHABLE");
}

This will send the data from the phone to the watch.

WCSession *session = [WCSession defaultSession];
NSError *error;

[session updateApplicationContext:@{@"firstItem": @"item1", @"secondItem":[NSNumber numberWithInt:2]} error:&error];

This will receive the data from the phone on the watch.

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

NSLog(@"%@", applicationContext);

item1 = [applicationContext objectForKey:@"firstItem"];
item2 = [[applicationContext objectForKey:@"secondItem"] intValue];
}

The WWDC2015 video on WatchConnectivity is really great, I recommend to check it out.

How to send data from iphone to watchkit in swift

Add this method in the AppDelegate:

func application(application: UIApplication!,
handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!,
reply: (([NSObject : AnyObject]!) -> Void)!)
{
//define your dictionary
reply(yourDict)
}

Add this anywhere in the Apple Watch Extension:

var dict = ["test" : 4] //your dictionary/request to sent to the iPhone
if !WKInterfaceController.openParentApplication(dict, reply: { (reply,error) -> Void in
println("\(reply)") //your reply data as Dictionary
}) {
println("ERROR")
}

The first function will trigger with WKInterfaceController.openParentApplication and will reply the dictionary in the reply parameter.

Developer forum:
https://devforums.apple.com/message/1082689#1082689

Passing Data From A Class To WatchOS 2 (Connectivity)

Yes, that is an incorrect assumption. The WCSession sendMessage documentation states that the dictionary may only contain property list types which are basic types such as strings, integers, floats, data, etc.
So to send your content, either convert the object to a dictionary of key-value pairs or use the less recommended approach of using NSKeyedArchiver to convert your object directly to data.

Apple Watch OS 2: Is there a to transfer data from iPhone to Watch App without Watch app being in foreground?

What you can do is to use the updateApplicationContext:error: method on WCSession object to send updated data to your watch. When your watch app wakes up, it will receive the context object with the updated data.

WatchKit 2.0 Send Message From Phone To Watch

It's only the "correct" method if you are looking to interactively communicate with a reachable device.

But you haven't shown where you set your session delegate or activated the session:

let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()

You may also want to add some checks to ensure that a watch is paired (session.paired), that the watch app is installed (session.watchAppInstalled), and that the watch is actually reachable (session.reachable) before trying to interactively communicate with it, to make your app more robust.

See this guide for more details.

You could also choose to fall back on a non-interactive (background) method to queue messages for your app until it is open and can receive them.

Send messages between iOS and WatchOS with WatchConnectivity in watchOS2

WatchConnectivity

First the two classes that are supposed to communicate with each other (iOS and watchOS) need to conform the <WCSessionDelegate> and #import the WatchConnectivity framework

Before you can send data you need to check if your device is able to send data

if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
NSLog(@"WCSession is supported");
}

Then if you wish to use "interactive messaging" (sendMessage APIs) you will need to see if the other device is reachable first:

if ([[WCSession defaultSession] isReachable]) {
//Here is where you will send you data
}

The "background operations" APIs do not require the counterpart device to be reachable at the point in time you call the WCSession API.

You have several options when it comes to transferring data between your apps, in the Apple Documentation they are described like this:

  • Use the updateApplicationContext:error: method to communicate only the most recent state information to the counterpart. When the counterpart wakes, it can use this information to update its own state and remain in sync. Sending a new dictionary with this method overwrites the previous dictionary.

  • Use the sendMessage:replyHandler:errorHandler: or sendMessageData:replyHandler:errorHandler: method to transfer data immediately to the counterpart. These methods are intended for immediate communication when your iOS app and WatchKit extension are both active.

  • Use the transferUserInfo: method to transfer a dictionary of data in the background. The dictionaries you send are queued for delivery to the counterpart and transfers continue when the current app is suspended or terminated.

  • Use the transferFile:metadata: method to transfer files in the background. Use this method in cases where you want to send more than a simple dictionary of values. For example, use this method to send images or file-based documents.

I will give you an example how to send/receive data with Application Context

Send data:

WCSession *session = [WCSession defaultSession];
NSError *error;

[session updateApplicationContext:@{@"firstItem": @"item1", @"secondItem":[NSNumber numberWithInt:2]} error:&error];

Receive data:

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

NSLog(@"%@", applicationContext);

NSString *item1 = [applicationContext objectForKey:@"firstItem"];
int item2 = [[applicationContext objectForKey:@"secondItem"] intValue];
}

For more information about WatchConnectivity I really recommend watching the WWDC2015 session video and reading the Apple Documentation on WatchConnectivity

Passing data to Apple Watch app

This applies to OS 1 only. See below for better answers.

I got it working using your method. I guess there's a couple of things you can check:

1) Are you synchronising the defaults after you set the value:

defaults?.synchronize();
NSLog("%@ ", defaults?.dictionaryRepresentation())

2) Have you enabled the App Group in both your app and your extension?

App Group capability for App Target
App Group capability for Watch Extension Target

3) Are you using the correctly named app group when constructing the NSDefaults? For example, I use:

NSUserDefaults(suiteName: "group.com.brindysoft.MyWatch");

Once all that's set up I run the app, set the value in the defaults, then run the glance target which reads the value from the default and that seems to work!

Sample Image


  1. Still stuck? check your app groups in your apple account

How to transfer a UIImage using Watch Connectivity

To transfer files between your iPhone and your Apple Watch you should use Watch Connectivity, using WCSession to handle the communication properly. You can send an UIImage as NSData using the didReceiveMessageData delegate method of the WCSessionDelegate.

The first thing you should know is convert your UIImage to NSData and viceversa. You can use for this the following code:

If PNG images

let image = UIImage(named: "nameOfYourImage.jpg")
let data = UIImagePNGRepresentation(image)

If JPG images

let image = UIImage(named: "nameOfYourImage.jpg")
let data = UIImageJPEGRepresentation(image, 1.0)

Then you can use the WCSession to send the message like in the following way:

ViewController.swift

class ViewController: UIViewController, WCSessionDelegate {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

if WCSession.isSupported() {
WCSession.defaultSession().delegate = self
WCSession.defaultSession().activateSession()
}

let image = UIImage(named: "index.jpg")!

let data = UIImageJPEGRepresentation(image, 1.0)

WCSession.defaultSession().sendMessageData(data!, replyHandler: { (data) -> Void in
// handle the response from the device

}) { (error) -> Void in
print("error: \(error.localizedDescription)")

}
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

InterfaceController.swift

import WatchKit
import Foundation
import WatchConnectivity

class InterfaceController: WKInterfaceController, WCSessionDelegate {

override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)

// Configure interface objects here.
}

override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()

if WCSession.isSupported() {
WCSession.defaultSession().delegate = self
WCSession.defaultSession().activateSession()
}
}

override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}

func session(session: WCSession, didReceiveMessageData messageData: NSData, replyHandler: (NSData) -> Void) {

guard let image = UIImage(data: messageData) else {
return
}

// throw to the main queue to upate properly
dispatch_async(dispatch_get_main_queue()) { [weak self] in
// update your UI here
}

replyHandler(messageData)
}
}

In the above code when you open the ViewController it sends the UIImage, the above example is only for learning purposes, you have to handle it in a more proper way regarding the complexity of your project.

I hope this help you.



Related Topics



Leave a reply



Submit