WatchKit return reply() 在 handleWatchKitExtensionRequest 的块内:
WatchKit return reply() inside a block in handleWatchKitExtensionRequest:
我看到 SO post 显然数据正在被获取并返回到 Watch 扩展,如下所示:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
{
if ( [[userInfo objectForKey:@"request"] isEqualToString:@"getData"] )
{
// get data
// ...
reply( data );
}
}
但是当我在获取网络数据后尝试在块内调用 'reply()' 时,如下所示:
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
{
NSMutableDictionary *response = [NSMutableDictionary dictionary];
[ClassObject getDataWithBlock:^(BOOL succeeded, NSError *error){
if (succeeded)
{
[response setObject:@"update succeded" forKey:@"updateKey"];
reply(response);
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
reply(response);
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
reply(response);
}
}
}];
}
dispatch_after(dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 180), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
});
我收到这个错误:
"The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]"
所以我想我必须立即调用 reply() 并且在 WatchKit 唤醒父应用程序后发送新网络数据的唯一方法是使用 MMWormhole?
为确保您的异步数据获取不会立即return(不调用回复),您可以尝试以下操作:
- (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"];
reply(response);
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
dispatch_semaphore_signal(sema);
reply(response);
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
dispatch_semaphore_signal(sema);
reply(response);
}
}
}];
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];
});
}
我认为您混淆了代码。您需要将 beginBackgroundTaskWithName
移动到您的 handleWatchKitExtensionRequest
中,将其作为您做的第一件事,然后调用您的函数。
简化示例:
-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask __block = [app beginBackgroundTaskWithName:@"watchAppRequest" expirationHandler:^{
NSLog(@"Background handler called. Background tasks expirationHandler called.");
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
//do your background task(s) here
if([requestString isEqualToString:@“myRequest"]){
//send reply back to watch
reply();
}
//end background task
[app endBackgroundTask:bgTask];
bgTask=UIBackgroundTaskInvalid;
}
始终参考官方文档。 Official Documentation
以下代码适合我。
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
[ClassObject getDataWithBlock:^(BOOL succeeded, NSError *error){
if (succeeded)
{
[response setObject:@"update succeded" forKey:@"updateKey"];
reply(response);
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
reply(response);
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
reply(response);
}
}
}];
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
我看到
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
{
if ( [[userInfo objectForKey:@"request"] isEqualToString:@"getData"] )
{
// get data
// ...
reply( data );
}
}
但是当我在获取网络数据后尝试在块内调用 'reply()' 时,如下所示:
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void ( ^)( NSDictionary * ))reply
{
NSMutableDictionary *response = [NSMutableDictionary dictionary];
[ClassObject getDataWithBlock:^(BOOL succeeded, NSError *error){
if (succeeded)
{
[response setObject:@"update succeded" forKey:@"updateKey"];
reply(response);
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
reply(response);
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
reply(response);
}
}
}];
}
dispatch_after(dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 180), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
});
我收到这个错误:
"The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]"
所以我想我必须立即调用 reply() 并且在 WatchKit 唤醒父应用程序后发送新网络数据的唯一方法是使用 MMWormhole?
为确保您的异步数据获取不会立即return(不调用回复),您可以尝试以下操作:
- (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"];
reply(response);
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
dispatch_semaphore_signal(sema);
reply(response);
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
dispatch_semaphore_signal(sema);
reply(response);
}
}
}];
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];
});
}
我认为您混淆了代码。您需要将 beginBackgroundTaskWithName
移动到您的 handleWatchKitExtensionRequest
中,将其作为您做的第一件事,然后调用您的函数。
简化示例:
-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask __block = [app beginBackgroundTaskWithName:@"watchAppRequest" expirationHandler:^{
NSLog(@"Background handler called. Background tasks expirationHandler called.");
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
//do your background task(s) here
if([requestString isEqualToString:@“myRequest"]){
//send reply back to watch
reply();
}
//end background task
[app endBackgroundTask:bgTask];
bgTask=UIBackgroundTaskInvalid;
}
始终参考官方文档。 Official Documentation
以下代码适合我。
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
[ClassObject getDataWithBlock:^(BOOL succeeded, NSError *error){
if (succeeded)
{
[response setObject:@"update succeded" forKey:@"updateKey"];
reply(response);
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
reply(response);
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
reply(response);
}
}
}];
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});