Лучший способ запустить несколько примеров запросов HealthKit?

У меня есть сценарий, в котором мне нужно получить несколько наборов данных из HealthKit — температуру тела, вес и кровяное давление. Мне нужны все 3, прежде чем я смогу продолжить обработку, потому что они закончатся в PDF.

Мой наивный первый подход будет запускать один, затем в HKSampleQuery resultsHandler вызывать второй, затем в этом resultsHandler вызывать третий. Такое чувство... не знаю... такое ощущение, что я что-то упускаю.

Есть ли лучший способ или разумен наивный подход?


person Mattio    schedule 24.04.2015    source источник


Ответы (3)


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

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

Поскольку обработчики запросов HealthKit вызываются в анонимной очереди фоновой отправки, убедитесь, что вы синхронизируете доступ к своему счетчику, либо защитив его блокировкой, либо изменив счетчик в последовательной очереди отправки, которой вы управляете, например в основной очереди.

person Allan    schedule 26.04.2015
comment
Небольшое замечание о предлагаемом подходе к отслеживанию выполнения запросов с помощью счетчика: вам следует обратить внимание на тот факт, что запросы HealthKit являются асинхронными, что означает, что вы должны защищать счетчик при его изменении. - person goldengil; 18.07.2016
comment
@goldengil Хороший вопрос, я собираюсь обновить ответ, чтобы включить это. - person Allan; 18.07.2016

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

Вот ссылка с примером: Использование групп отправки для ожидания нескольких веб-служб

person StevenOjo    schedule 03.02.2016
comment
Комментарий к ссылке: возможно ли, чтобы первый вызов веб-службы вернулся до того, как второй вызов веб-службы будет добавлен в группу отправки? Если да, то dispatch_group_notify() будет вызвана до завершения второго запроса веб-службы. Было бы лучшим решением вызвать dispatch_group_enter(serviceGroup); один за другим, прежде чем сделать какой-либо вызов веб-службы? - person bickster; 14.12.2016
comment
@bickster, если вызовы dispatch_group_enter выполняются до уведомления, вы в безопасности. Если первый завершится до того, как мы получим уведомление, тогда уведомление будет просто ждать второго. Если они оба завершены, уведомление просто заблокирует его. Диспетчерские группы GCD представляют собой крайнюю абстракцию многопоточности, поэтому они облегчают жизнь, но вы все равно должны быть осторожны. Если вы не можете вызывать свои входы и уведомления по порядку, вы можете немного углубиться в GCD, чтобы получить больше контроля. - person Ryan Klein; 17.01.2017
comment
@bickster и чтобы уточнить, что я имею в виду, если вы не можете вызывать свои входы и уведомления по порядку, они должны происходить синхронно в одном потоке. Если вы делаете вызов для входа в асинхронный поток, который выполняется после уведомления, то обратный вызов уведомления будет выполнен неожиданно. Здесь есть хорошее обсуждение групповое обсуждение GCD - person Ryan Klein; 17.01.2017

Вы захотите использовать группы отправки GCD.

Сначала настройте глобальную переменную для основного потока.

var GlobalMainQueue: dispatch_queue_t {
  return dispatch_get_main_queue()
}

Затем создайте группу рассылки:

let queryGroup = dispatch_group_create()

Прямо перед выполнением ваших запросов вызовите:

dispatch_group_enter(queryGroup)

После выполнения запроса вызовите:

dispatch_group_leave(queryGroup)

Затем обработайте код завершения:

dispatch_group_notify(queryGroup, GlobalMainQueue) {
  // completion code here
}
person ultraflex    schedule 13.02.2016