Inconsistent behaviour in openParentApplication in my WatchKit App

I'm developing an Apple Watch application that uses the

openParentApplication:reply:
method to communicate with its parent app.

The parent app communicates with a web service and sends back the data it gets to the watch extension by means of calling the

reply
method with a
NSDictionary
containing the data.


The app works perfectly when the parent app is open in the foreground or background. But if I open the parent app and then terminate it using the task switcher, the first time the watch extension sends a request, it gets the following error and the parameter

replyInfo
comes in as nil.


UIApplicationDelegate in the iPhone App never called reply()


The weird thing is, every single

openParentApplication:replyInfo:
call the extension makes after that gets a proper response. It's as if the
handleWatchKitExtensionRequest:reply:
method in the parent is doesn't get called when the app is first launched the first time after it was killed.


What could be the possible reason for this?


I'm performing all operations in the

handleWatchKitExtensionRequest:reply:
in a background task, as suggested in the docs. Here's some of my code:


Code from my extension:

NSDictionary *params = @{@"requestCode": @(SHBRequestGetLoggedIn)}; [WKInterfaceController openParentApplication:params reply:^(NSDictionary *replyInfo, NSError *error) { 
     // Do something with the result
}];


Code from the parent app:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
    }];

    NSNumber* requestCode = userInfo[@"requestCode"];

    switch ([requestCode intValue])
    {
        // Perform some request and then call reply()

        // End the background task
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        });
    }
}

I'm having the same exact issue. The first time I call openParentApplication it fails, then if I call it again it works perfectly. It seems like that the parent app needs more time to open, but it doesn't make any sense because I use a dispatch_after with 5 seconds and I get the failing response almost immediately.


Did you find a way to solve this?



UPDATE


I wrote this workaround that it's working for me so far. I pass 2 as tries value, since the failing call is usually just the first one. I know it's ugly, but it's the more robust I found so far.


BTW, in which cases can openParentApplication return with false? I didn't find anything in the documentation.


extension WKInterfaceController {
    class func openParentApplication(var #tries: Int, userInfo: [NSObject : AnyObject], reply: (([NSObject : AnyObject]!, NSError!) -> Void)?) -> Bool {
   
        tries = tries-1
     
        let success = self.openParentApplication(userInfo, reply: { (data, error) -> Void in
         
            if let error = error where tries > 0 {
                Log.error("Obtained error, trying again. Left tries: \(tries)")
                self.openParentApplication(tries: tries, userInfo: userInfo, reply: reply)
            } else {
                Log.trace("Request terminated with data: \(data), error: \(error)")
                reply?(data, error)
            }
        })
     
        if !success && tries > 0 {
            Log.trace("Request failed, trying again")
            return self.openParentApplication(tries: tries, userInfo: userInfo, reply: reply)
        }
     
        return success
    }
}

I'm having the same exact issue.

i use this code first time it's dosent work

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
   
    __block UIBackgroundTaskIdentifier bogusWorkaroundTask;
    bogusWorkaroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
    });
   
    __block UIBackgroundTaskIdentifier realBackgroundTask;
    realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        reply(nil);
        [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
    }];
   

    reply(@{@"Confirmation" : @"Text was received."});
   
    [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
   
  
   
   
}

what can i do for recall in frist time and reciving the result , please in Objective C

I also am seeing this exact behavior. This seems like a regression in iOS9 beta.

Same problem here

You have to call reply as soon as possible (even with nil argument) in handleWatchKitExtensionRequest method.

This is the code I use in my App and it works good!


- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
    // set a background task
    __block UIBackgroundTaskIdentifier backgroundTask;
    backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
        [application endBackgroundTask:backgroundTask];
        backgroundTask = UIBackgroundTaskInvalid;
        reply(nil);
    }];

    // get clipID
    uint8_t clipID = [[userInfo valueForKey:@"refresh"] unsignedIntValue];

    // sanity check
    if (clipID < 8) {
        // send reply
        NSDictionary *replyDict = [NSDictionary dictionaryWithObject:@(clipID) forKey:@"wait"];
        reply(replyDict);
    }
    else {
        reply(nil);
    }

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 2), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // end background task
        [application endBackgroundTask:backgroundTask];
        backgroundTask = UIBackgroundTaskInvalid;
    } );
}
Inconsistent behaviour in openParentApplication in my WatchKit App
 
 
Q