How do I correctly use “openParentApplication” and “handleWatchKitExtensionRequest” so that “reply()” is called?

匿名 (未验证) 提交于 2019-12-03 01:33:01

问题:

Situation: I use openParentApplication in the Watch app to call handleWatchKitExtensionRequest in the main app. This works nicely in the simulator and it also works on the actual devices (Apple Watch and iPhone) when the iPhone app is active/open.

Problem: When I run it on the actual devices (Apple Watch and iPhone), handleWatchKitExtensionRequest does not return data to openParentApplication when the main iPhone app is not active/open.

Code in InterfaceController.m in the WatchKit Extension:

NSDictionary *requst = @{ @"request" : @"getData" }; [InterfaceController openParentApplication:requst                                      reply:^( NSDictionary *replyInfo, NSError *error ) {                                         // do something with the returned info                                      }]; 

Code in the app delegate of the main app on iPhone:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply {   if ( [[userInfo objectForKey:@"request"] isEqualToString:@"getData"] )   {     // get data     // ...     reply( data );   } } 

回答1:

When the main app on the iPhone is not active, reply() may not be reached because the background task is killed by the OS before.

The solution is to explicitly start a background task in handleWatchKitExtensionRequest as specified in the documentation. If a background task is initiated like this, it can run up to 180 seconds. This ensures that the main app on the iPhone is not suspended before it can send its reply.

Code in the app delegate of the main app on 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];    } ); } 

In case you need to asynchroneously fetch data, use the following approach to ensure that the method does not return immediately (without calling reply):

- (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];   }); } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!