Ios iPhone应用程序中的UIApplicationLegate从未调用过reply

Ios iPhone应用程序中的UIApplicationLegate从未调用过reply,ios,watchkit,apple-watch,Ios,Watchkit,Apple Watch,我正在尝试使用以下代码从watch simulator启动我的iPhone应用程序: WKInterfaceController子类 [WKInterfaceController openParentApplication:[NSDictionary dictionaryWithObject:@"red" forKey:@"color"] reply:^(NSDictionary *replyInfo, NSError *error) { NSLog(@"replyInfo %@",replyI

我正在尝试使用以下代码从watch simulator启动我的iPhone应用程序:

WKInterfaceController子类

[WKInterfaceController openParentApplication:[NSDictionary dictionaryWithObject:@"red" forKey:@"color"] reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(@"replyInfo %@",replyInfo);
NSLog(@"Error: %@",error);
}];
AppDelegate.m

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
NSLog(@"appdelegate handleWatchKitExtensionRequest");
NSLog(@"NSDictionary: %@",userInfo);
NSLog(@"replyInfo: %@",replyInfo);
}
我得到的错误是:

错误:错误域=com.apple.watchkit.errors代码=2“该 iPhone应用程序中的UIApplicationLegate从未在中调用reply() -[UIApplicationLegate应用程序:handleWatchKitExtensionRequest:答复:] UserInfo=0x7f8603227730{NSLocalizedDescription= iPhone应用程序中的UIApplicationLegate从未在中调用reply() -[UIApplicationLegate应用程序:handleWatchKitExtensionRequest:回复:]


即使返回
nil
,也需要调用reply块。以下内容将解决您的错误:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
NSLog(@"appdelegate handleWatchKitExtensionRequest");
NSLog(@"NSDictionary: %@",userInfo);
NSLog(@"replyInfo: %@",replyInfo);
reply(nil);
}

有关更多信息,请参阅。您还可以返回NSDictionary
回复(myNSDictionary)
返回到Watchkit扩展名可能有用的任何信息,尽管字典只能包含可序列化为属性列表文件的信息,例如,您可以传递字符串,但不能只传递包含对自定义类实例引用的字典,而不首先将它们打包为NSData

除了不调用应答块之外,发生这种情况至少有两个原因:

  • 您的iPhone应用程序在处理请求时崩溃,因此无法调用应答块。检查并确保您没有意外地将nil放入NSMutableDictionary,因为这将导致崩溃
  • 您正试图将无法序列化为plist文件的内容放入replyInfo字典(指向@duncan babbage的提示)。如果需要传递NSAttributedString或自定义对象,请确保其符合NSCoding,然后执行以下操作:
  • 在电话端,建立您的回复字典:

    NSMutableDictionary *reply = [NSMutableDictionary new];
    MyCustomObject *myObject = <something you need to send>;
    reply[@"myKey"] = [NSKeyedArchiver archivedDataWithRootObject: myObject];
    NSAttributedString *myString = <some attributed string>;
    reply[@"otherKey"] = [NSKeyedArchiver archivedDataWithRootObject: myString];
    

    我想补充一点,在中指定的handleWatchKitExtensionRequest中启动后台任务非常重要。这确保了iPhone上的主应用程序在发送回复之前不会被挂起。(不启动后台任务不会在模拟器中或iPhone应用程序处于活动状态时导致问题。但是,在iPhone应用程序处于非活动状态时会导致问题。)

    iPhone上主应用程序的应用程序代理中的代码:

    - (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
    {
       __block UIBackgroundTaskIdentifier watchKitHandler;
       watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
                                                                   expirationHandler:^{
                                                                     watchKitHandler = UIBackgroundTaskInvalid;
                                                                   }];
    
       if ( [[userInfo objectForKey:@"request"] isEqualToString:@"getData"] )
       {
          // get data
          // ...
          reply( data );
       }
    
       dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1 ), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
           [[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
        } );
    }
    

    我根本不知道WatchKit,但错误似乎表明
    handleWatchKitExtensionRequest:
    中的代码必须调用作为该方法参数提供的reply()块。尝试添加
    reply(@{@“数据”:@“测试数据”})到该方法。这只是使用一个微不足道的字典作为测试;我猜WatchKit文档会告诉您该词典的确切内容。是的,当我在[InterfaceController openParentApplication:dict reply:^(NSDictionary*replyInfo,NSError*error){NSLog(@“%@,[replyInfo objectForKey:@“Key”]);NSLog(@“error:-%@)中打印错误时,我也会遇到同样的错误,[错误描述]);请建议如何从该方法获取watchkit应用程序中的数据。我想从我的应用程序中获取字符串到watchkit应用程序。感谢advanceWow,我花了很长时间才意识到你不能在replyInfo字典中传递自定义对象。即使遵守NSCoding也不行。当真正的问题是replyInfo字典。@bdmontz与XPC服务不同,它似乎没有注册自定义类的规定。糟糕!也许你应该将其作为另一个答案发布。我不明白为什么openParentApplication reply块需要错误参数,但handleWatchKitExtensionRequest块没有错误参数参数传回?如果iPhone应用程序在处理请求时崩溃,您也会收到此错误。如果iPhone处于非活动状态,我也会收到此
    错误:error Domain=com.apple.watchkit.errors code=2“iPhone应用程序中的UIApplicationLegate从未在-[UIApplicationLegate应用程序:handleWatchKitExtensionRequest:reply:]中调用reply()UserInfo=0x7f8603227730{NSLocalizedDescription=iPhone应用程序中的UIApplicationLegate从未在-[UIApplicationLegate应用程序:handleWatchKitExtensionRequest:reply:]中调用过reply()
    错误您忘了提到要使用归档,您需要遵守协议
    ,该协议要求实现其所需的方法。@EridB,这是错误的。正如我在回答中所述,您的对象必须符合NSCoding协议才能使用归档。@bdmontz谢谢您保存了我的培根!我已经花了一整天的时间来尝试解决这个问题了出局了!我还做了一个很好的词典分类来隐藏所有这些垃圾。
    - (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
    {
       __block UIBackgroundTaskIdentifier watchKitHandler;
       watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
                                                                   expirationHandler:^{
                                                                     watchKitHandler = UIBackgroundTaskInvalid;
                                                                   }];
    
       if ( [[userInfo objectForKey:@"request"] isEqualToString:@"getData"] )
       {
          // get data
          // ...
          reply( data );
       }
    
       dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1 ), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
           [[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
        } );
    }