12

我正在尝试使用以下代码从手表模拟器启动我的 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 应用程序中的 UIApplicationDelegate 从未在 -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:] 中调用回复()”UserInfo=0x7f8603227730 {NSLocalizedDescription=iPhone 中的 UIApplicationDelegate应用程序从未在 -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]} 中调用 reply()

4

3 回答 3

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

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

于 2015-01-08T11:03:55.433 回答
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];

然后在手表端打开包装:

NSData *objectData = replyInfo[@"myKey"];
MyCustomObject *myObject = [NSKeyedUnarchiver unarchiveObjectWithData: objectData];
NSData *stringData = replyInfo[@"otherKey"];
NSAttributedString *myString = [NSKeyedUnarchiver unarchiveObjectWithData: stringData];
于 2015-03-17T15:19:56.873 回答
6

我想补充一点,在文档中指定的 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];
    } );
}
于 2015-05-03T14:45:53.230 回答