Watchkit - 应用程序:handleWatchKitExtensionRequest 错误

Watchkit -application: handleWatchKitExtensionRequest error

通过上述方法请求 XML 项的字典时出现以下错误:

> NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]

我传递一个由 NSStrings 的 NSMutableArray 组成的 NSDictionary 没问题。

来自界面控制器:

- (void) requestFeedsFromPhone
{
    [WKInterfaceController openParentApplication:@{@"request":@"feeds"}
                                       reply:^(NSDictionary *replyInfo, NSError *error) {

                                           // the request was successful
                                           if(error == nil) {

                                               // get the array of items
                                               NSMutableDictionary *tempDictionary = replyInfo[@"feeds"];


                                               NSLog(@"tempDictionary: %@", tempDictionary[@"feedsArray"]);
                                               self.feeds = tempDictionary[@"feedsArray"];
                                               [self setupTable];
                                           }
                                           else{
                                               NSLog(@"ERROR: %@", error);
                                           }
                                       }];
}

在应用委托中:

- (void) application:(UIApplication *)application
handleWatchKitExtensionRequest:(NSDictionary *)userInfo
           reply:(void (^)(NSDictionary *))reply
{

    MasterViewController *mainController = (MasterViewController*)  self.window.rootViewController;

    //this is the troublesome line - calling this method results in the error
    NSDictionary *feedsDictionary = [mainController returnFeedsDictionary];

    reply(@{@"feeds": feedsDictionary});
}

在 MasterViewController 中:

-(NSDictionary *) returnFeedsDictionary
{

    NSURL *url = [NSURL URLWithString:@"http://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss"];
    SeparateParser *separateParser = [[SeparateParser alloc] initWithURL:url];
    [separateParser parse];
    NSArray *tempArray = [separateParser returnFeeds];
    return @{@"feedsArray": tempArray};

}

returnFeeds 方法 returns NSMutableDictionarys 的 NSMutableArray 填充了 NSMutableStrings(标题,link,imageURL 等)。

我假设我的问题是我的一些数据不符合 属性 列表,但我认为数组、字符串和字典是可以接受的。

handleWatchKitExtensionRequest 中,确保您启动了 documentation 中指定的后台任务。这确保 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];
    } );
}

您可能想尝试在您的回复字典中使用 NSKeyedArchiver。由于数据的序列化问题,我遇到了这个问题,这很有帮助。

您正在点击 Law of Leaky Abstractions

您的 iPhone-App 和 WatchKit-Extension 运行 作为两个独立的进程和两个独立的沙箱。 OpenParentApplication/handleWatchKitExtensionRequest/reply机制只是Apple提供的一种包装进程内通信的便利机制。

抽象泄漏:

回复(feedsDictionary)

returned字典只能包含

  • NSData
  • NSString
  • NSDate
  • NSArray
  • NSDictionary

    如果您的 return 字典包含超出此范围的任何内容,例如自定义 class 实例,然后你会收到那个糟糕的错误,说 reply() 是 从来没有打过电话,即使你打过电话!



解决方案 1:序列化您的对象并将其从应用程序发送到手表,然后在手表上反序列化(又名 Marshalling/Unmarshalling)。

  • 这需要使用 NSCoding,如上文所述post:序列化为 NSData* 流,发送回复(dataStream),然后在 WatchKit 扩展中反序列化。
  • NSCoding 很痛苦。您需要在发送前显式使用 NSKeyedArchiver 进行序列化,并使用 NSKeyedUnarchiver 进行反序列化 tutorial here.
  • 需要大量的代码来支持 class 对象本身中的 encode/Decode(以满足 NSCoder)

解决方案 2: 只需传递一个字符串作为 Key,并在 Watch Extension 中实例化您的对象(而不是传递胖对象实例本身)

  • 允许 WatchKit Extension 针对您的 class 文件进行编译,方法是单击 {class}.m,按 command+option+1,然后单击“. ..WatchKit Extension" Target Membership 下的复选框(无论如何你都需要这样做,即使使用解决方案 1)

  • 例如您的 WatchKit 扩展将 alloc/init 模型的新实例,而不是试图将其传递给

  • 例如您可以将 URL 作为字符串传递,WatchKit 扩展将进行 NSURLConnection 调用。