Reputation: 3134
I can't get didReceiveApplicationContext
to be called. Any ideas?
InterfaceController
:
import WatchKit
import Foundation
import WatchConnectivity
class InterfaceController: WKInterfaceController, WCSessionDelegate {
@IBOutlet var colorLabel: WKInterfaceLabel!
private let session: WCSession? = WCSession.isSupported() ? WCSession.defaultSession() : nil
override init() {
super.init()
session?.delegate = self
session?.activateSession()
}
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
}
func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]){
let colors : String = applicationContext["color"] as! String
colorLabel.setText(colors)
NSLog("session did receive application context")
}
}
I've been following along with this tutorial: http://www.kristinathai.com/watchos-2-how-to-communicate-between-devices-using-watch-connectivity/
No NSLog
or setting of the colorLabel
happens. No idea what I'm missing. Thanks!
Upvotes: 5
Views: 5014
Reputation: 2033
This seems to be a typical 'development phase' problem!
The WCSession.defaultSession.applicationContext is buffered on the iOS device, so it is only transferred to the watch (extension) once if it doesn't change.
This lead to the strange finding, that watch extensions 'didReveiveApplicationContext:' seems not to be called, when WCSession.defaultSession.updateApplicationContext is called in the iOS app again. (Try to call WSSession.defaultSession.receivedApplicationContext in the extension to find, that the earlier transferred context is in fact available)!
In test situations, it is very helpful to add a 'changer' object to the context dictionary (like an UUID object, or - maybe even better - a NSDate.date). This will ensure, that the context has changed (compared to the buffered one) and gets transferred again (leading to a call to didReceiveApplicationContext) :-)
NSError* error = nil;
[WCSession.defaultSession updateApplicationContext:@{ @"yourKey" : @"your content",
@"forceTransfer" : NSDate.date }
error:&error];
And: Don't forget to remove this in the production version of your app, as - of course - this leads to unneeded data transfer between your app and your watch extension!
PS: The checked answer solves this problem by creating a new app. And flushing all buffers this way...
Upvotes: 13
Reputation: 21
Check the session to make sure its isPaired and watchAppInstalled properties are both YES. It seems like updating the shared context while these are NO will not work.
I was having this issue. Made a change to not update the context when either condition was NO. Added an implementation of sessionWatchStateDidChange:, and if both conditions were YES, updated the context. It worked.
I suspect this in combination with another issue where the phone will not send the context if the data is not different causes the "never updating" issue. A workaround of passing a "uuid" did help but I suspect the above is a better fix.
Upvotes: 2
Reputation: 15217
In my case, I used the following code to send my application context:
do {
try session.updateApplicationContext(applicationContext)
} catch let error {
throw error
}
and neither didReceiveApplicationContext
was called, nor an error was thrown.
My problem was that applicationContext
contained a custom object, whereas only property list items are allowed.
The strange point is that no error was thrown.
Upvotes: 1
Reputation: 1480
For me, when doing some testing/debugging i tried to fire updateApplicationContext
in AppDelegate
. This caused the didReceiveApplicationContext
not being called.
Moving this logic to a later point, like in a UIViewController
made it work for me at least.
Upvotes: 2
Reputation: 778
I had the same problem. In my case it helped to just close both simulators and then run the Watch scheme. This opens up both simulators again in connected state.
Hoping it helps!
Upvotes: 4
Reputation: 414
I copied the above code into a new watch app and it works fine. The error must lay on the sending side. Are you certain the code in the iOS app is being called? I presume you are using Xcode and two simulators, one for the iOS app and one for the WatchApp.
The code on the iOS side is not run unless you open the app on the phone simulator. Where and how on the iOS side are you issuing the updateAppContext call?
In my test, this is all that I added to my ViewController.swift on the iOS side (This code will not be triggered until I start the iOS app on my iPhone.)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
do {
try session.updateApplicationContext( ["color" : "Red" ])
} catch _ {
}
}
Upvotes: 2