iPhone App 中的 UIApplicationDelegate 从未调用过 reply
The UIApplicationDelegate in the iPhone App never called reply
我正在尝试使用以下代码从手表模拟器启动我的 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);
}
我得到的错误是:
Error: Error Domain=com.apple.watchkit.errors Code=2 "The
UIApplicationDelegate in the iPhone App never called reply() in
-[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]"
UserInfo=0x7f8603227730 {NSLocalizedDescription=The
UIApplicationDelegate in the iPhone App never called reply() in
-[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}
您需要调用回复块,即使您 return 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。您还可以 return 一个 NSDictionary reply(myNSDictionary);
,其中包含任何对 return 您的 Watchkit 扩展有用的信息,尽管字典只能包含可序列化为 [=22= 的信息] 列表文件,因此例如您可以传递字符串,但不能只传递包含对自定义 类 实例的引用的字典,而不先将它们打包为 NSData。
除了不调用回复块之外,发生这种情况至少有几个原因:
- 您的 iPhone 应用程序在处理请求时崩溃,因此无法调用回复块。检查你是否不小心将 nil 放入 NSMutableDictionary,因为这会导致崩溃。
- 您正在尝试将无法序列化到 plist 文件中的内容放入 replyInfo 字典(向@duncan-babbage 致敬)。如果您需要传递 NSAttributedString 或您的自定义对象,请确保它符合 NSCoding 并执行此操作:
在 phone 端构建您的回复字典:
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];
我想补充一点,在 documentation 中指定的 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];
} );
}
我正在尝试使用以下代码从手表模拟器启动我的 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);
}
我得到的错误是:
Error: Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x7f8603227730 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}
您需要调用回复块,即使您 return 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。您还可以 return 一个 NSDictionary reply(myNSDictionary);
,其中包含任何对 return 您的 Watchkit 扩展有用的信息,尽管字典只能包含可序列化为 [=22= 的信息] 列表文件,因此例如您可以传递字符串,但不能只传递包含对自定义 类 实例的引用的字典,而不先将它们打包为 NSData。
除了不调用回复块之外,发生这种情况至少有几个原因:
- 您的 iPhone 应用程序在处理请求时崩溃,因此无法调用回复块。检查你是否不小心将 nil 放入 NSMutableDictionary,因为这会导致崩溃。
- 您正在尝试将无法序列化到 plist 文件中的内容放入 replyInfo 字典(向@duncan-babbage 致敬)。如果您需要传递 NSAttributedString 或您的自定义对象,请确保它符合 NSCoding 并执行此操作:
在 phone 端构建您的回复字典:
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];
我想补充一点,在 documentation 中指定的 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];
} );
}