objective c WatchKit WKInterfaceController openParentApplication无限期地调用阻塞

时间:2015-07-25 01:53:12

标签: xcode watchkit blocking wkinterfacecontroller

我使用以下代码"简单地"从我的监视应用程序确定父应用程序的应用程序状态:

WatchKit扩展:

[WKInterfaceController openParentApplication:[NSDictionary dictionary] reply:^(NSDictionary *replyInfo, NSError *error)
    {
        UIApplicationState appState =  UIApplicationStateBackground;
        if(nil != replyInfo)
            appState = (UIApplicationState)[((NSNumber*)[replyInfo objectForKey:kAppStateKey]) integerValue];

        //handle app state
    }];

主要应用程序:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply
{
    __block UIBackgroundTaskIdentifier realBackgroundTask;

    realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

        reply([NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:[[UIApplication sharedApplication] applicationState]], kAppStateKey, nil]);
        [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
    }];

    reply([NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:[[UIApplication sharedApplication] applicationState]], kAppStateKey, nil]);

    [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
}

当应用程序位于前台时,它可以100%正常工作。当应用程序被"最小化"或者"终止"这可能在50%的时间内工作(可能更少)。如果它不起作用,它似乎无限期地阻塞。例如,在1分钟后,我启动父应用程序,调用(openParentApplication)立即返回状态" UIApplicationStateBackground" (我发布应用程序之前的状态,因为如果我启动应用程序,应用程序显然不处于后台状态。)

BTW:我正在使用真实硬件进行测试。

我做错了什么?即使我创建后台任务,为什么iOS在接到呼叫后立即让我的主应用程序进入睡眠状态?这是一个完整的节目。

任何想法或建议都将不胜感激!!

1 个答案:

答案 0 :(得分:0)

经过一些研究后,它看起来是个已知问题。例如,以下链接标识了此问题并提供了解决方案:

http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply

然而,这个解决方案对我不起作用。因此,我实施了以下解决方案(它有点草率,但这是故意帮助压缩解决方案):

//start the timeout timer
timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeOutTime target:self selector:@selector(onTimeout) userInfo:nil repeats:NO];

//make the call
messageSent = [WKInterfaceController openParentApplication:[NSDictionary dictionary] reply:^(NSDictionary *replyInfo, NSError *error)
{
  if(nil != _stateDelegate)
  {     
    UIApplicationState appState =  UIApplicationStateBackground;
    if(nil != replyInfo)
      appState = (UIApplicationState)[((NSNumber*)[replyInfo objectForKey:kAppStateKey]) integerValue];

    [_stateDelegate onOperationComplete:self timeout:false applicationState:appState];
    _stateDelegate = nil;
   }
}];

//if the message wasn't sent, then this ends now
if(!messageSent)
{
   if(nil != _stateDelegate)
   {
      //just report that the main application is inactive
      [_stateDelegate onOperationComplete:self timeout:false applicationState:UIApplicationStateInactive];
   }
   _stateDelegate = nil;
}


-(void)onTimeout
{
    timeoutTimer = nil;
    if(nil != _stateDelegate)
    {
        [_stateDelegate onOperationComplete:self timeout:true applicationState:UIApplicationStateInactive];
    }
    _stateDelegate = nil;
}

简而言之,如果计时器在我从主应用程序收到回复之前触发,我将基本上假设主应用程序已经进入睡眠状态。请记住,所有挂起的呼叫都会在某个时刻成功(例如,应用状态恢复为活动状态),因此,您需要处理此方案(如有必要)。