我的WatchKit应用程序中openParentApplication的行为不一致

Cih*_*Tek 8 ios apple-watch watchkit

我正在开发一个Apple Watch应用程序,它使用该openParentApplication:reply:方法与其父应用程序进行通信.

父应用程序与Web服务通信,并通过调用包含数据的reply方法将其获取的数据发送回监视扩展NSDictionary.

当父应用程序在前台或后台打开时,该应用程序可以正常运行.但是,如果我打开父应用程序,然后使用任务切换器终止它,则第一次监视扩展程序调用时openParentApplication:replyInfo:,会收到以下错误,参数replyInfo以nil结尾.

UIApplicationDelegate in the iPhone App never called reply()

但是openParentApplication:replyInfo:,在获得适当的响应之后,扩展所做的每一次调用.

我查了一下,发现手表扩展第一次拨打电话时,handleWatchKitExtensionRequest:reply:永远不会在父应用上调用.

可能的原因是什么?

handleWatchKitExtensionRequest:reply:正如文档中所建议的那样,我正在后台任务中执行所有操作.这是我的一些代码:来自我的扩展程序的代码:

NSDictionary *params = @{@"requestCode": @(RequestGetLoggedIn)};

[WKInterfaceController openParentApplication:params reply:^(NSDictionary *replyInfo, NSError *error) {
    // Do something with the result
}];
Run Code Online (Sandbox Code Playgroud)

来自父应用的代码:

- (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];
    });
}
Run Code Online (Sandbox Code Playgroud)

编辑1:问题出现在模拟器和真正的Apple Watch上.

Cih*_*Tek 5

看起来iOS 8.4中存在一个错误.

我已经添加了NSLogs,application:didFinishLaunchingWithOptions:handleWatchKitExtensionRequest:reply:执行了导致问题的操作,然后检查了设备日志并得到了:

--- 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)**
Run Code Online (Sandbox Code Playgroud)

此日志显示application:didFinishLaunchingWithOptions:在操作系统发出有关未从父应用程序获取响应的错误后调用.如果应用程序没有首先启动,该应用程序将如何回复?

openParentApplication:reply:当发生此问题时,我通过再次调用该方法暂时解决了该问题.

我实现重试一次行为的方式是创建一个包装调用并使用该方法而不是原始方法的方法.我将此作为类方法添加到实用程序类中,但它也可以是全局函数.

+ (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);
    }];
}
Run Code Online (Sandbox Code Playgroud)

  • 而不是if(replyInfo == nil),你可以使用(error.domain == WatchKitErrorDomain AND error.code == WatchKitApplicationDelegateWatchKitRequestReplyNotCalledError) (2认同)