我如何通过completionHandlers等待多个功能?

时间:2018-09-05 15:44:59

标签: objective-c react-native asynchronous grand-central-dispatch homekit

我目前正在为React-Native的HomeKit搭建桥梁,我必须读取HomeKit值才能返回Java代码。

要读取特征的最新值,我们必须使用readValueWithCompletionHandler,直到该值完成才准备就绪。因此,我必须阅读这些特征中的6个,并将每个特征分配给我的NSMutableDictionary对象,以返回React-Native进行处理。

与其在前一个completionHandler内将每个读取嵌套在最后一个return accObject内,不如在completionHandlers之前等待所有return完成的最干净的方法是

我一直在搜索semaphoresDispatchGroup和其他几个解决方案,但对如何解决这个问题却一无所知。

(粗略的)示例:

NSMutableDictionary *accObject = [[NSMutableDictionary alloc] initWithCapacity: 6];

[charac1 readValueWithCompletionHandler:^(NSError *error) {
        if (error) {
          RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
        }
        RCTLog(@"READ SETPOINT VALUE: %@", charac1.value);
        accObject[@"charac1"] = charac1.value;
      }];
...

[charac6 readValueWithCompletionHandler:^(NSError *error) {
        if (error) {
          RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
        }
        RCTLog(@"READ SETPOINT VALUE: %@", charac6.value);
        accObject[@"charac6"] = charac6.value;
      }];

 return accObject;

4 个答案:

答案 0 :(得分:1)

在这种情况下,我建议使用dispatch_group_t等待读取值,并使用完成块来处理返回的值。

- (void)readValuesWithCompletionHandler:(void(^)(NSDictionary* values))completion {
  NSMutableDictionary *accObject = [[NSMutableDictionary alloc] initWithCapacity: 6];

  // Initialize |charac1|, |charac2|, ...

  dispatch_group_t group = dispatch_group_create();

  dispatch_group_enter(group);
  [charac1 readValueWithCompletionHandler:^(NSError *error) {
    if (error) {
      RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
    }
    RCTLog(@"READ SETPOINT VALUE: %@", charac1.value);
    accObject[@"charac1"] = charac1.value;
    dispatch_group_leave(group);
  }];

  // ... Do same thing with another values

  dispatch_group_enter(group);
  [charac6 readValueWithCompletionHandler:^(NSError *error) {
    if (error) {
      RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
    }
    RCTLog(@"READ SETPOINT VALUE: %@", charac6.value);
    accObject[@"charac6"] = charac6.value;
    dispatch_group_leave(group);
  }];

  dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    if (completion) {
      completion(accObject);
    }
  });
}

用法:

[self readValuesWithCompletionHandler:^(NSDictionary *values) {
  // Do whatever you want with |values| after reading
}];

答案 1 :(得分:1)

您可以在等待dispatch_semaphore_wait()的情况下使用dispatch_semaphore_t 您可以使用此过程为我完成这项工作。

     dispatch_semaphore_t sem = dispatch_semaphore_create(0);


    dispatch_async(dispatch_get_main_queue(), ^{
            NSMutableDictionary *accObject = [[NSMutableDictionary alloc] initWithCapacity: 6];

[charac1 readValueWithCompletionHandler:^(NSError *error) {
        if (error) {
          RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
        }
        RCTLog(@"READ SETPOINT VALUE: %@", charac1.value);
        accObject[@"charac1"] = charac1.value;
      }];
...

[charac6 readValueWithCompletionHandler:^(NSError *error) {
        if (error) {
          RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
        }
        RCTLog(@"READ SETPOINT VALUE: %@", charac6.value);
        accObject[@"charac6"] = charac6.value;
      }];


            dispatch_semaphore_signal(sem);
        });

         dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
 return accObject;

答案 2 :(得分:0)

认为我已经找到了基于this article的解决方案。

NSMutableDictionary *accObject = [[NSMutableDictionary alloc] initWithCapacity: 6];
dispatch_group_t group = dispatch_group_create();

dispatch_group_enter(group);
[charac1 readValueWithCompletionHandler:^(NSError *error) {
        if (error) {
          RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
        }
        RCTLog(@"READ SETPOINT VALUE: %@", charac1.value);
        accObject[@"charac1"] = charac1.value;
        dispatch_group_leave(group);
      }];
...

dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{
        // Now call the final completion block
        return accObject;
    });

答案 3 :(得分:0)

您可以在此处使用调度组,即不能返回值,但可以调用完成块。该完成块可以作为函数的参数存在。

 NSMutableDictionary *accObject = [[NSMutableDictionary alloc] initWithCapacity: 6];
    dispatch_group_t group = dispatch_group_create();

[charac1 readValueWithCompletionHandler:^(NSError *error) {
        dispatch_group_enter(group);
        if (error) {
          RCTLog(@"ERROR READING HOMEKIT VALUE: %@", error);
        }
        RCTLog(@"READ SETPOINT VALUE: %@", charac1.value);
        accObject[@"charac1"] = charac1.value;
        dispatch_group_leave(group);
      }];
...

dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{
        // Now here instead of returning a value, you can call a completion handler.
    });