2

Okay so I'm making this Apple Watch app and in my Watch App, I have a button. When you touch the button, it does this:

[WKInterfaceController openParentApplication:[NSDictionary dictionary] reply:^(NSDictionary *replyInfo, NSError *error) {
    if(error) {
        NSLog(@"%@",error);
    }
}];

And in my App Delegate file I do this:

-(void) application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
    //Code that is not importent and is confidential
    reply([NSDictionary dictionary]);
}

Yet I get this error when I press the button:

Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x7fd2b9c35ae0 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}

I'm calling reply() as shown above but it doesn't see that! Also, it's ignoring the other code I have in there!

Can anybody explain why this is happening?

Nathan S.
  • 5,244
  • 3
  • 45
  • 55
Nerdy Lime Apps
  • 331
  • 2
  • 5
  • 18
  • 1
    Never having used this, I would defer to the documentation which says: `Because this method is likely to be called while your app is in the background, call the beginBackgroundTaskWithName:expirationHandler: method at the start of your implementation and the endBackgroundTask: method after you have processed the reply and executed the reply block. Starting a background task ensures that your app is not suspended before it has a chance to send its reply.` So perhaps give that a try – Louis Tur Mar 23 '15 at 22:07
  • 1
    @LouisTur Thanks for commenting! Could you give me an example of those methods cause I was having trouble implementing them? – Nerdy Lime Apps Mar 24 '15 at 02:18
  • An educated guess, try removing the lines of code you have in the handleWatch method and let us know the results. – Ashraf Tawfeeq Mar 24 '15 at 05:32
  • Please check my answer here: http://stackoverflow.com/a/31994232 – Vivienne Fosh Aug 30 '15 at 23:31

4 Answers4

3

From the documentation:

replyInfo: A dictionary containing data to return to the WatchKit app. The contents of the dictionary must be serializable to a property list file. The contents of this dictionary are at your discretion and you may specify nil.

If you don't send a valid dictionary, you will not get a reply.

david72
  • 7,151
  • 3
  • 37
  • 59
1

You need to perform all work in handleWatchKitExtensionRequest in a background task. You can find the documentation here: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

This blog post may also prove helpful: http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply

bgilham
  • 5,909
  • 1
  • 24
  • 39
  • So I've been changing some stuff and trying the things you guys have suggested. Here is my new code (that's not working): – Nerdy Lime Apps Mar 26 '15 at 15:53
  • In watch app (in button):NSLog(@"button pressed"); [WKInterfaceController openParentApplication:[NSDictionary dictionary] reply:^(NSDictionary *replyInfo, NSError *error) { if(error) { NSLog(@"%@",replyInfo); NSLog(@"%@",error); } }]; NSLog(@"app opened?"); – Nerdy Lime Apps Mar 26 '15 at 15:54
  • In iPhone App (that's not even getting called):- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier { } - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(NSString *)taskName expirationHandler:(void (^)(void))handler { NSLog(@"backgroundBegunDelegate?"); return UIBackgroundTaskInvalid; } – Nerdy Lime Apps Mar 26 '15 at 15:59
  • - (void)application:(UIApplication*)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply { NSLog(@"in handle watch"); //confidential code that gives away what the app is (uses UILocalNotification is that is important) if (success) { //a boolean i made earlier in the function reply(@{"YES" :@"Success"}); } else { reply(@{"NO" :@"Success"}); } } – Nerdy Lime Apps Mar 26 '15 at 15:59
  • My output is: button pressed, app opened? for every time I press the button. I don't know why its not working! – Nerdy Lime Apps Mar 26 '15 at 16:00
0

The error "Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" generally means that your app's handleWatchKitExtensionRequest had an error and/or did not call reply() or call it correctly.

The documentation is here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleWatchKitExtensionRequest:reply:

Here is a bit of simple sample code using a NSDictionary response.

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply{
    NSLog(@"containing app received message from watch");
    NSDictionary *response = @{@"response" : @"MyResponse"};
    reply(response);
}
Bill Bunting
  • 521
  • 6
  • 28
0

You may have trouble if your dictionary includes custom classes. Try to send simple strings first and see if that makes a difference.

Check that your "important and confidential" code does not raise exception, or finish without calling a reply (with a error payload, for example).

Your "important and confidential" code must be really quick. If that is not the case, you have to use a background task (see here for examples).

Finally, consider using a background task if your code takes time, does network access. If you use asynchronous network tasks (recommended), reply when you receive the answer, and finish the background task at that time.

Last but not least, the first call to parentApplication fails on some iOS versions : Inconsistent behavior of openParentApplication in my WatchKit App. This solved the last issue for me!

Hope that helps ;-)

Community
  • 1
  • 1
blackbox
  • 671
  • 6
  • 18