I am trying to launch my iPhone app from watch simulator using the below code :
WKInterfaceController subclass
[WKInterfaceController op
I would like to add that it is important to start a background task in handleWatchKitExtensionRequest as specified in the documentation. This ensures that the main app on the iPhone is not suspended before it can send its reply. (Not initiating a background task does not cause a problem in the simulator or when the iPhone app is active. However, it causes a problem when the iPhone app is inactive.)
Code in the app delegate of the main app on iPhone:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
{
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
if ( [[userInfo objectForKey:@"request"] isEqualToString:@"getData"] )
{
// get data
// ...
reply( data );
}
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1 ), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
[[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
} );
}
Aside from just not calling the reply block, this can happen for at least a couple reasons:
On the phone side build your reply dictionary:
NSMutableDictionary *reply = [NSMutableDictionary new];
MyCustomObject *myObject = <something you need to send>;
reply[@"myKey"] = [NSKeyedArchiver archivedDataWithRootObject: myObject];
NSAttributedString *myString = <some attributed string>;
reply[@"otherKey"] = [NSKeyedArchiver archivedDataWithRootObject: myString];
And unpack it back on the watch side:
NSData *objectData = replyInfo[@"myKey"];
MyCustomObject *myObject = [NSKeyedUnarchiver unarchiveObjectWithData: objectData];
NSData *stringData = replyInfo[@"otherKey"];
NSAttributedString *myString = [NSKeyedUnarchiver unarchiveObjectWithData: stringData];
You need to call the reply block, even if you return nil
. The following will resolve your error:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
NSLog(@"appdelegate handleWatchKitExtensionRequest");
NSLog(@"NSDictionary: %@",userInfo);
NSLog(@"replyInfo: %@",replyInfo);
reply(nil);
}
See the Apple documentation for further information. You can also return an NSDictionary reply(myNSDictionary);
with whatever information it would be useful to return to your Watchkit extension, although the dictionary can only contain information that can be serializable to a property list file, so for instance you can pass strings but you can't just pass a dictionary containing references to instances of your custom classes without packaging them up as NSData first.