【问题标题】:objective c WatchKit WKInterfaceController openParentApplication call blocks indefinitelyObjective c WatchKit WKInterfaceController openParentApplication 调用无限期阻塞
【发布时间】:2015-07-25 01:53:12
【问题描述】:

我正在使用以下代码从我的手表应用中“简单地”确定父应用的应用状态:

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”(在我启动应用程序之前的状态,如果我很明显应用程序不处于后台状态启动它)。

顺便说一句:我正在使用真实硬件进行测试。

我做错了什么?为什么即使我创建了后台任务,iOS 也会在接到电话后立即让我的主应用程序进入睡眠状态?这是一个完整的表演停止者。

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

【问题讨论】:

    标签: xcode watchkit blocking wkinterfacecontroller


    【解决方案1】:

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

    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;
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 1970-01-01
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      • 2012-05-14
      • 1970-01-01
      相关资源
      最近更新 更多