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 调用。
通过上述方法请求 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 调用。