Inconsistent behavior of openParentApplication in my WatchKit App

孤人 提交于 2019-12-04 11:16:10

问题


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 makes a call to openParentApplication:replyInfo:, it gets the following error and the parameter replyInfo comes in as nil.

UIApplicationDelegate in the iPhone App never called reply()

But every single openParentApplication:replyInfo: call the extension makes after that gets a proper response.

I checked and found out that the first time the watch extension makes the call, the handleWatchKitExtensionRequest:reply: is never get called on the parent app.

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": @(RequestGetLoggedIn)};

[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"];

    // 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];
    });
}

Edit 1: The problem occurs both on the Simulator and on a real Apple Watch.


回答1:


It looks like there's a bug in iOS 8.4.

I've added NSLog's to the beginning of application:didFinishLaunchingWithOptions: and handleWatchKitExtensionRequest:reply:, performed the actions that lead to the problem and then checked the device log and got this:

--- Notice>: (Warn ) WatchKit: <SPCompanionAppServer.m __91-[SPCompanionAppServer launchCompanionAppForGizmoAppWithIdentifier:withUserInfoData:reply:]_block_invoke_2:1450> Got BSActionErrorCodeResponseNotPossible for com.xyz.xyz.watchkitapp. This will translate to WatchKitApplicationDelegateWatchKitRequestReplyNotCalledError

... Irrelevant stuff

--- WatchKit Extension[1686] <Warning>: __59-[InformationController getNotificationListIncremental:]_block_invoke (null)
**--- <Warning>: MY LOG: Application did launch with parameters (null)**

This log shows that application:didFinishLaunchingWithOptions: gets called AFTER the OS gives an error about not getting a response from the parent app. How's the app gonna give a response if it's not getting launched first?

I've temporarily solved the problem by calling the openParentApplication:reply: method again when this problem occurs.

The way I've implemented the retry once behaviour is by creating a method that wraps the call and using that one instead the original method. I added this as a class method to a utility class, but it can be a global function as well.

+ (void)openParentApplication:(NSDictionary*)params reply:(void(^)(NSDictionary *replyInfo, NSError *error))reply
{
    [WKInterfaceController openParentApplication:params reply:^(NSDictionary *replyInfo, NSError *error) {
        if (error.domain == WatchKitErrorDomain && error.code == WatchKitApplicationDelegateWatchKitRequestReplyNotCalledError)
        {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [WKInterfaceController openParentApplication:params reply:^(NSDictionary *replyInfo, NSError *error) {
                    reply(replyInfo, error);
                }];
            });
        }
        else
            reply(replyInfo, error);
    }];
}



回答2:


I am getting the same issue. See the following bare bones project I made for a bug report to Apple: https://www.dropbox.com/s/ayltpprjck37ins/HandleWatchkitExtensionError%202.zip?dl=0.

@Cihan Tek - how are you calling openParentApplication:reply: again? Are you calling it in the reply block? I am still receiving the error when I do that.



来源:https://stackoverflow.com/questions/31210092/inconsistent-behavior-of-openparentapplication-in-my-watchkit-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!