UIApplicationDelegate в приложении iPhone никогда не вызывал ответ
Я пытаюсь запустить приложение для 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 "UIApplicationDelegate в приложении iPhone никогда не вызывал ответ() в - [Приложение UIApplicationDelegate: handleWatchKitExtensionRequest: reply:]" UserInfo = 0x7f8603227730 {NSLocalizedDescription = UIApplicationDelegate в приложении iPhone никогда не вызывал ответ() в - [Приложение UIApplicationDelegate: handleWatchKitExtensionRequest: reply:]}
Ответы
Ответ 1
Вам нужно вызвать блок ответа, даже если вы вернете 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.
Ответ 2
Помимо того, что вы не вызываете блок ответа, это может произойти по крайней мере по нескольким причинам:
- Ваше приложение iPhone разбилось, когда оно обрабатывало запрос и поэтому никогда не могло вызвать блок ответа. Убедитесь, что вы случайно не вставляете nil в NSMutableDictionary, так как это приведет к сбою.
- Вы пытаетесь поставить что-то, что не может быть сериализовано в файл 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];
Ответ 3
Я хотел бы добавить, что важно запустить фоновое задание в handleWatchKitExtensionRequest, как указано в documentation. Это гарантирует, что основное приложение на 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];
} );
}