Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Apple Health (HealthKit) и FHIR
Читайте данные Apple Watch и Apple Health через HealthKit на Swift, по местному времени, и записывайте их в FHIR R4: разрешения, фоновая синхронизация, правила Apple.
Данные Apple Watch хранятся в Apple Health на сопряженном iPhone, и единственный способ их прочитать — это HealthKit, из приложения на этом iPhone, с разрешения пользователя. Чтобы поместить их в запись FHIR, читайте ежедневную статистику с помощью HKStatisticsCollectionQuery, отправляйте значения на ваш бэкенд и записывайте каждую метрику как Observation с кодом LOINC и единицей измерения UCUM. На этой странице показан код на Swift (проверенный на соответствие SDK iOS 17), разрешения и правила, установленные Apple, а также как значения становятся FHIR R4 Observations.
Что содержится в Apple Health
Apple Health собирает данные, которые измеряют iPhone и Apple Watch — частоту сердечных сокращений, частоту сердечных сокращений в покое, вариабельность сердечного ритма (SDNN), уровень кислорода в крови, частоту дыхания, шаги, расход энергии, стадии сна, уведомления о нерегулярном ритме, записи ЭКГ — а также данные, которые записывают другие приложения: Garmin Connect, Oura, Withings Health Mate, умные весы, тонометры, глюкометры. Таким образом, чтение данных Apple Health охватывает больше, чем только данные Apple Watch.
Сервера HealthKit или веб-API не существует. Данные остаются на устройстве (и в зашифрованной резервной копии iCloud пользователя); ваше приложение считывает их локально.
Разрешения
- Включите возможность HealthKit в Xcode и добавьте
NSHealthShareUsageDescriptionвInfo.plist(плюсNSHealthUpdateUsageDescription, только если вы пишете). - Запросите необходимые типы. Пользователи могут разрешить одни типы и отказаться от других, при этом HealthKit не сообщает вашему приложению, был ли отклонен доступ на чтение: отклоненный тип просто возвращает пустые данные. Разработайте экраны для случая "нет данных", а не для ошибки.
- Запрашивайте разрешения в момент подключения пользователя, с пояснением причины, а не при первом запуске приложения.
Чтение ежедневных значений в Swift
import Foundation
import HealthKit
/// One day of Apple Health data, ready to send to your backend.
struct DailyValue: Codable {
let metric: String // "heart_rate", "steps"
let day: String // "2026-10-01", the user's local day
let value: Double
let min: Double?
let max: Double?
}
let store = HKHealthStore()
let heartRate = HKQuantityType(.heartRate)
let steps = HKQuantityType(.stepCount)
func requestAccess() async throws {
// Read-only: the app never writes to Apple Health.
try await store.requestAuthorization(toShare: [], read: [heartRate, steps])
}
/// Daily statistics for the last `days` days, one value per local calendar day.
func dailyValues(_ type: HKQuantityType, metric: String, unit: HKUnit,
options: HKStatisticsOptions, days: Int) async throws -> [DailyValue] {
let calendar = Calendar.current
let end = calendar.startOfDay(for: Date()).addingTimeInterval(86_400)
let start = calendar.date(byAdding: .day, value: -days, to: end)!
let query = HKStatisticsCollectionQueryDescriptor(
predicate: HKSamplePredicate.quantitySample(type: type,
predicate: HKQuery.predicateForSamples(withStart: start, end: end)),
options: options,
anchorDate: start,
intervalComponents: DateComponents(day: 1))
let collection = try await query.result(for: store)
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
var out: [DailyValue] = []
collection.enumerateStatistics(from: start, to: end) { stats, _ in
let day = fmt.string(from: stats.startDate)
if options.contains(.cumulativeSum), let sum = stats.sumQuantity() {
out.append(DailyValue(metric: metric, day: day, value: sum.doubleValue(for: unit), min: nil, max: nil))
} else if let avg = stats.averageQuantity() {
out.append(DailyValue(metric: metric, day: day, value: avg.doubleValue(for: unit),
min: stats.minimumQuantity()?.doubleValue(for: unit),
max: stats.maximumQuantity()?.doubleValue(for: unit)))
}
}
return out
}
func collect() async throws -> [DailyValue] {
try await requestAccess()
let bpm = HKUnit.count().unitDivided(by: .minute())
let hr = try await dailyValues(heartRate, metric: "heart_rate", unit: bpm,
options: [.discreteAverage, .discreteMin, .discreteMax], days: 30)
let st = try await dailyValues(steps, metric: "steps", unit: .count(), options: .cumulativeSum, days: 30)
return hr + st // POST these to your backend, which writes them to the FHIR record
}
Почему статистические запросы вместо чтения выборок: HKStatisticsCollectionQuery возвращает итоговые данные и средние значения за день, которые Apple Health уже дедуплицировал по источникам, поэтому шаги, подсчитанные как iPhone, так и Watch, не суммируются дважды. Чтение необработанных выборок и их самостоятельное суммирование является наиболее распространенным источником завышенного количества шагов.
Дни — это местные календарные дни человека (Calendar.current). Сохраняйте их такими же до записи FHIR, где effectivePeriod объекта Observation представляет собой этот местный день с его смещением часового пояса.
Поддержание актуальности записи
- При открытии: каждый раз, когда приложение выходит на передний план, считывайте количество дней с момента последней успешной синхронизации. Это надежная основа.
- В фоновом режиме:
HKObserverQueryсenableBackgroundDelivery(for:frequency:)пробуждает ваше приложение при поступлении новых данных; для этого требуется разрешение HealthKit на фоновую доставку, а фактическое время определяет iOS. - Первое подключение: импортируйте ограниченную историю (например, 30 дней), а не за годы, затем двигайтесь вперед.
От значений Swift к FHIR Observations
Отправьте массив DailyValue на ваш бэкенд и запишите одно Observation для каждого человека, метрики и дня со стабильным идентификатором, обновляя его, когда наступает тот же день снова. Таблица сопоставления (тип HealthKit → LOINC → UCUM), проверенный пример JSON и код TypeScript, выполняющий это обновление (upsert), запускаемый на платформе, находятся в разделе Wearable data in FHIR. Коды для двух метрик здесь:
| HealthKit | LOINC | UCUM | Значение за день |
|---|---|---|---|
heartRate |
8867-4 Heart rate | /min |
среднее, с минимумом и максимумом в качестве компонентов |
stepCount |
41950-7 Number of steps in 24 hour | {steps} |
общее |
Правила Apple для медицинских данных
- Руководство по обзору приложений 5.1.3: медицинские данные не могут использоваться для рекламы или анализа данных, не могут передаваться третьим лицам без согласия пользователя, а личная медицинская информация не может храниться в iCloud.
- Ваша политика конфиденциальности должна указывать, что вы читаете и почему; Apple проверяет это.
- Данные, записываемые вашим приложением в Apple Health, приписываются вашему приложению; данные, которые вы читаете, сохраняют свой исходный источник (
HKSource), который вы должны указывать в записи как исходную систему.
Apple Health Records
Отдельно от данных о физической активности, Apple Health может хранить клинические записи, загруженные из участвующих медицинских систем (в основном в США), и HealthKit предоставляет их в виде объектов HKClinicalRecord, которые содержат исходный ресурс FHIR. Для их чтения требуются отдельные разрешения и права доступа. Это другая интеграция по сравнению с данными с носимых устройств, и Anpheros Daily в настоящее время их не считывает.
Место Anpheros в системе
Платформа Anpheros хранит результат: запись FHIR R4 о человеке, где каждое значение с носимого устройства представлено как Observation, помеченное как данные устройства, согласие для других приложений, информация о происхождении (provenance) и журнал доступа. Anpheros не читает Apple Health напрямую — это происходит в вашем iOS-приложении. Собственное приложение Anpheros, Anpheros Daily, читает Apple Health на iPhone (планы Plus и Max) и записывает ежедневные сводки в запись с указанными выше кодами.
Часто задаваемые вопросы
Могу ли я читать данные Apple Watch с сервера?
Нет. Данные Apple Watch синхронизируются с Apple Health на сопряженном iPhone, и HealthKit может использоваться только приложением на этом устройстве. Приложение считывает данные и отправляет их на ваш сервер.
Существует ли веб-API или REST API для Apple Health?
Нет. Apple не предлагает веб- или REST API для Apple Health: HealthKit работает только внутри приложения на iPhone (или Apple Watch) пользователя. Чтобы использовать данные на сервере, ваше приложение считывает их с разрешения пользователя и отправляет, например, в виде FHIR Observations в Anpheros.
Нужен ли мне API-ключ или плата за Apple Health API?
Ключ и плата не требуются: HealthKit является частью iOS. Вам потребуется возможность HealthKit в вашем приложении, описание использования для каждого типа данных и разрешение пользователя; проверка App Store проверяет, как вы используете данные.
Как узнать, отказал ли пользователь в доступе к типу HealthKit?
Вы не можете узнать об этом для доступа на чтение: HealthKit скрывает эту информацию для защиты конфиденциальности, и отказанный тип не возвращает никаких данных. Обрабатывайте "нет данных" как нормальное состояние и предоставьте способ просмотра разрешений в приложении Health.
Почему мои счетчики шагов выше, чем в приложении Health?
Вероятно, вы суммируете необработанные выборки из нескольких источников (iPhone и Watch). Используйте HKStatisticsCollectionQuery с .cumulativeSum, что применяет собственное дедупликацию Apple Health.
Какой код LOINC соответствует вариабельности сердечного ритма Apple Watch?
Apple Health хранит HRV как SDNN, что соответствует LOINC 80404-7. Health Connect хранит RMSSD, другую статистику, поэтому не смешивайте их под одним кодом.
Связанные материалы
- Данные носимых устройств в FHIR: таблица соответствия и бэкенд-код
- Health Connect в FHIR: то же самое на Android
- Как создать приложение для личной медицинской карты
- Как создать медицинское приложение с использованием Flutter
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card