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