Ответ 1
Если основное приложение на iPhone неактивно, reply()
может не быть достигнуто, потому что передняя задача была убита ОС раньше.
Решение состоит в том, чтобы явно запустить фоновое задание в handleWatchKitExtensionRequest
, как указано в documentation. Если фоновое задание инициируется таким образом, оно может работать до 180 секунд. Это гарантирует, что основное приложение на 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];
} );
}
Если вам нужно асинхронно извлекать данные, используйте следующий подход, чтобы гарантировать немедленный возврат метода (без ответа на вызов):
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
{
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
NSMutableDictionary *response = [NSMutableDictionary dictionary];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[ClassObject getDataWithBlock:^(BOOL succeeded, NSError *error){
if (succeeded)
{
[response setObject:@"update succeded" forKey:@"updateKey"];
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
}
}
reply(response);
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
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];
});
}