iPhone应用程序中的UIApplicationDelegate从未调用过回复

Abh*_*edi 12 ios apple-watch watchkit

我正在尝试使用以下代码从手表模拟器启动我的iPhone应用程序:

WKInterfaceController子类

[WKInterfaceController openParentApplication:[NSDictionary dictionaryWithObject:@"red" forKey:@"color"] reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(@"replyInfo %@",replyInfo);
NSLog(@"Error: %@",error);
}];
Run Code Online (Sandbox Code Playgroud)

AppDelegate.m

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
NSLog(@"appdelegate handleWatchKitExtensionRequest");
NSLog(@"NSDictionary: %@",userInfo);
NSLog(@"replyInfo: %@",replyInfo);
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

错误:错误Domain = com.apple.watchkit.errors Code = 2"iPhone App中的UIApplicationDelegate从未调用reply() - [UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]"UserInfo = 0x7f8603227730 {NSLocalizedDescription = iPhone中的UIApplicationDelegate应用程序永远不会调用reply() - [UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}

Dun*_*age 18

即使您返回,也需要调用回复块nil.以下将解决您的错误:

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

有关详细信息,请参阅Apple文档.您还可以返回一个NSDictionary,reply(myNSDictionary);其中包含返回到您的Watchkit扩展名的任何信息,尽管该字典只能包含可以序列化到属性列表文件的信息,因此例如您可以传递字符串,但不能只是传递包含对自定义类实例的引用的字典,而不首先将它们打包为NSData.

  • 哇,让我永远意识到你不能在replyInfo字典中传递自定义对象.即使符合NSCoding也不会这样做.当真正的问题是replyInfo字典时,表示你从未调用过回复块的错误消息会产生误导. (8认同)
  • 如果iPhone应用程序在处理请求时崩溃,您也会收到此错误. (2认同)

bdm*_*ntz 14

除了不调用回复块之外,这可能至少有几个原因:

  1. 您的iPhone应用程序在处理请求时崩溃,因此无法调用回复块.检查您是否不小心将nil放入NSMutableDictionary中,因为这会导致崩溃.
  2. 你试图将一些无法序列化的东西放入一个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];
Run Code Online (Sandbox Code Playgroud)

然后将其打开放回手表侧:

NSData *objectData = replyInfo[@"myKey"];
MyCustomObject *myObject = [NSKeyedUnarchiver unarchiveObjectWithData: objectData];
NSData *stringData = replyInfo[@"otherKey"];
NSAttributedString *myString = [NSKeyedUnarchiver unarchiveObjectWithData: stringData];
Run Code Online (Sandbox Code Playgroud)


vom*_*ako 6

我想补充一点,在文档中指定的handleWatchKitExtensionRequest中启动后台任务很重要.这可以确保iPhone上的主应用程序在发送回复之前不会被暂停.(不启动后台任务不会在模拟器中或iPhone应用程序处于活动状态时出现问题.但是,当iPhone应用程序处于非活动状态时会导致问题.)

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

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