【问题标题】:WatchKit return reply() inside a block in handleWatchKitExtensionRequest:WatchKit 在handleWatchKitExtensionRequest 的块内返回reply():
【发布时间】:2015-05-09 06:57:06
【问题描述】:

我看到this SO 的帖子显然正在获取数据并返回到 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];
});

我收到此错误:

“iPhone App 中的 UIApplicationDelegate 从未在 -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:] 中调用 reply()”

所以我想我必须立即调用 reply() 并且在 WatchKit 唤醒父应用程序后发送新网络数据的唯一方法是使用 MMWormhole?

【问题讨论】:

    标签: ios objective-c watchkit apple-watch


    【解决方案1】:

    为确保您的异步数据获取不会立即返回(不调用回复),您可以尝试以下操作:

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

    【讨论】:

    • 我已经将它包装在后台任务中。我应该说清楚并更新我的问题。我什至尝试将时间更改为 180 秒,但它仍然会立即返回错误。在您的示例中,您是否在“获取数据”中运行了一个块?
    • 你好,我已经相应地改变了我的答案。这样一秒钟就足够了,因为程序在dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 处等待,直到dispatch_semaphore_signal(sema); 被执行。有用吗?
    • 它对我不起作用。我也这样做了。只是对我不起作用:(
    【解决方案2】:

    始终参考官方文档。 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;
    });
    

    【讨论】:

      【解决方案3】:

      我认为您的代码混淆了。您需要将 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;
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多