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

时间:2015-01-08 08:20:34

标签: ios watchkit apple-watch

我正尝试使用以下代码从手表模拟器启动我的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);
}

我得到的错误是:

  

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

3 个答案:

答案 0 :(得分: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);
}

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

答案 1 :(得分:14)

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

  1. 您的iPhone应用在处理请求时崩溃,因此无法调用回复块。检查您是否不小心将nil放入NSMutableDictionary,因为这会导致崩溃。
  2. 你试图将一些无法序列化的东西放入一个plist文件到replyInfo字典中(帽子提示为@duncan-babbage)。如果需要传递NSAttributedString或自定义对象,请确保它符合NSCoding并执行此操作:
  3. 在手机端构建您的回复词典:

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

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

    NSData *objectData = replyInfo[@"myKey"];
    MyCustomObject *myObject = [NSKeyedUnarchiver unarchiveObjectWithData: objectData];
    NSData *stringData = replyInfo[@"otherKey"];
    NSAttributedString *myString = [NSKeyedUnarchiver unarchiveObjectWithData: stringData];
    

答案 2 :(得分:6)

我想补充一点,在documentation中指定的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];
    } );
}