Как мне ожидать нескольких функций с завершением работы? - PullRequest
0 голосов
/ 05 сентября 2018

В настоящее время я работаю над мостом для HomeKit для React-Native, и мне нужно прочитать значения HomeKit, чтобы получить код Javascript.

Чтобы прочитать последнее значение признака, мы должны использовать readValueWithCompletionHandler , где значение не готово до его завершения. Поэтому я должен прочитать 6 из этих характеристик и назначить каждую из них моему NSMutableDictionary объекту, который будет возвращен для обработки React-Native.

Вместо того, чтобы вкладывать каждое чтение внутри предыдущего completionHandler с return accObject внутри последнего, каков самый чистый подход к ожиданию завершения всех completionHandlers до return.

Я некоторое время искал, смотрел на semaphores, DispatchGroup и пару других решений без отличного представления о том, как решить эту проблему.

Для (грубого) примера:

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 голосов
/ 12 сентября 2018

вы можете использовать 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;
0 голосов
/ 06 сентября 2018

Здесь вы можете использовать группу рассылки, используя которую вы не можете вернуть значение, но можете вызвать блок завершения. Этот блок завершения может быть там как параметры ваших функций.

 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.
    });
0 голосов
/ 08 сентября 2018

В этом случае я предлагаю использовать 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
}];
0 голосов
/ 05 сентября 2018

Думаю, я пришел к решению, основанному на этой статье .

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