# Apple Health (HealthKit) do FHIR

> Čtěte data z Apple Watch a Apple Health pomocí HealthKit v Swift, za den, a zapisujte je do záznamu FHIR R4: oprávnění, synchronizace na pozadí, pravidla Apple.

Source: https://developers.anpheros.com/cs/guides/apple-health-fhir

**Data z Apple Watch žijí v Apple Health na spárovaném iPhonu a jediný způsob, jak je číst, je HealthKit, z aplikace na tomto iPhonu, s povolením osoby.** Chcete-li je zapsat do záznamu FHIR, čtěte denní statistiky pomocí `HKStatisticsCollectionQuery`, odešlete hodnoty na svůj backend a zapište každou metriku jako Observation s kódem LOINC a jednotkou UCUM. Tato stránka ukazuje kód v Swiftu (typově kontrolovaný proti SDK pro iOS 17), oprávnění a pravidla, která Apple stanovuje, a jak se hodnoty stávají FHIR R4 Observations.

## Co je v Apple Health

Apple Health shromažďuje to, co iPhone a Apple Watch měří — srdeční tep, klidový srdeční tep, variabilitu srdečního tepu (SDNN), hladinu kyslíku v krvi, dechovou frekvenci, kroky, energii, fáze spánku, upozornění na nepravidelný srdeční rytmus, záznamy EKG — a to, co zapisují jiné aplikace: Garmin Connect, Oura, Withings Health Mate, chytré váhy, monitory krevního tlaku, glukometry. Čtení Apple Health tedy pokrývá více než jen Apple Watch.

Neexistuje žádný HealthKit server ani webové API. Data zůstávají na zařízení (a v šifrované záloze iCloudu dané osoby); vaše aplikace je čte lokálně.

## Oprávnění

1. Zapněte funkci **HealthKit** v Xcode a přidejte `NSHealthShareUsageDescription` do `Info.plist` (plus `NSHealthUpdateUsageDescription`, pouze pokud zapisujete).
2. Požádejte o typy, které potřebujete. Uživatelé mohou povolit některé a odmítnout jiné a **HealthKit vaší aplikaci neřekne, zda byl přístup ke čtení zamítnut**: zamítnutý typ jednoduše nevrátí žádná data. Navrhněte obrazovky pro "žádná data" namísto pro chybu.
3. Požádejte v okamžiku, kdy se uživatel připojí, s vysvětlením proč, nikoli při prvním spuštění.

## Čtení denních hodnot v Swiftu

```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
}
```

Proč statistické dotazy místo čtení vzorků: `HKStatisticsCollectionQuery` vrací celkové denní součty a průměry, které již Apple Health de-duplikoval napříč zdroji, takže kroky počítané iPhonem i hodinkami se nepřičítají dvakrát. Čtení surových vzorků a jejich vlastní sčítání je nejčastějším zdrojem nadhodnocených počtů kroků.

Dny jsou lokální kalendářní dny osoby (`Calendar.current`). Udržujte je takto až do FHIR záznamu, kde `effectivePeriod` Observation je tento lokální den s jeho časovým posunem.

## Udržování záznamu aktuálního

- **Při otevření:** Pokaždé, když se aplikace dostane do popředí, přečtěte počet dní od poslední úspěšné synchronizace. Toto je spolehlivý základ.
- **Na pozadí:** `HKObserverQuery` s `enableBackgroundDelivery(for:frequency:)` probudí vaši aplikaci, když dorazí nová data; vyžaduje to oprávnění pro doručování na pozadí HealthKit a iOS rozhoduje o skutečném načasování.
- **První připojení:** Importujte omezenou historii (například 30 dní) namísto let, a poté postupujte vpřed.

## Z hodnot Swift na FHIR Observation

Odešlete pole `DailyValue` na váš backend a vytvořte jednu Observation pro každou osobu, metriku a den se stabilním identifikátorem, přičemž ji aktualizujte, když stejný den přijde znovu. Mapovací tabulka (HealthKit type → LOINC → UCUM), validní JSON příklad a TypeScript kód, který provádí tento upsert, spuštěný proti platformě, jsou na [Wearable data in FHIR](https://developers.anpheros.com/cs/guides/wearable-data-fhir). Kódy pro dvě zde uvedené metriky jsou:

| HealthKit | LOINC | UCUM | Hodnota za den |
|---|---|---|---|
| `heartRate` | 8867-4 Heart rate | `/min` | průměrná, s minimem a maximem jako komponenty |
| `stepCount` | 41950-7 Number of steps in 24 hour | `{steps}` | celková |

## Pravidla společnosti Apple pro zdravotní data

- Pokyn pro revizi aplikací 5.1.3: zdravotní data nesmí být použita pro reklamu nebo těžbu dat, nesmí být sdílena s třetími stranami bez souhlasu osoby a osobní zdravotní informace nesmí být uloženy v iCloudu.
- Vaše zásady ochrany osobních údajů musí uvádět, co čtete a proč; Apple to kontroluje.
- Data zapsaná vaší aplikací do Apple Health jsou připsána vaší aplikaci; data, která čtete, si zachovávají svůj původní zdroj (`HKSource`), který byste měli do záznamu zahrnout jako zdrojový systém.

## Apple Health Records

Odděleně od dat o kondici, Apple Health může uchovávat klinické záznamy stažené z účastnících se zdravotnických systémů (převážně ve Spojených státech) a HealthKit je zpřístupňuje jako `HKClinicalRecord` objekty, které nesou původní FHIR zdroj. Jejich čtení vyžaduje vlastní oprávnění a nárok. Jedná se o jinou integraci než data z nositelných zařízení a Anpheros Daily je dnes nečte.

## Kde Anpheros zapadá

Platforma Anpheros ukládá výsledek: záznam osoby ve formátu FHIR R4, s každou hodnotou z nositelného zařízení jako Observation označenou jako data zařízení, souhlas pro jiné aplikace, původ dat a protokol přístupu. Sama o sobě nečte Apple Health – to probíhá ve vaší iOS aplikaci. Vlastní aplikace Anpheros, **Anpheros Daily**, čte Apple Health na iPhonu (plány Plus a Max) a zapisuje denní souhrny do záznamu s výše uvedenými kódy.

## Často kladené dotazy

### Mohu číst data z Apple Watch ze serveru?
Ne. Data z Apple Watch se synchronizují do aplikace Apple Health na spárovaném iPhonu a HealthKit lze použít pouze aplikací na tomto zařízení. Aplikace čte data a odesílá je na váš server.

### Existuje webové API nebo REST API pro Apple Health?
Ne. Apple nenabízí žádné webové ani REST API pro Apple Health: HealthKit běží pouze uvnitř aplikace na iPhonu (nebo Apple Watch) uživatele. Pro použití dat na serveru je vaše aplikace přečte s povolením uživatele a odešle je, například jako FHIR Observations do Anpheros.

### Potřebuji API klíč nebo platit za Apple Health API?
Žádný klíč ani poplatek: HealthKit je součástí iOS. Potřebujete v aplikaci povolenou funkci HealthKit, popis použití pro každý datový typ a povolení uživatele; recenze v App Store kontroluje, jak data používáte.

### Jak poznám, že uživatel odmítl přístup k typu HealthKit?
Pro přístup ke čtení to nepoznáte: HealthKit to skrývá, aby chránil soukromí, a odmítnutý typ nevrátí žádná data. Zacházejte s "žádná data" jako s normálním stavem a nabídněte možnost zkontrolovat oprávnění v aplikaci Health.

### Proč jsou moje počty kroků vyšší než v aplikaci Health?
Pravděpodobně sčítáte surové vzorky z několika zdrojů (iPhone a Watch). Použijte `HKStatisticsCollectionQuery` s `.cumulativeSum`, které aplikuje vlastní deduplikaci Apple Health.

### Který LOINC kód odpovídá variabilitě srdeční frekvence Apple Watch?
Apple Health ukládá HRV jako SDNN, což odpovídá LOINC 80404-7. Health Connect ukládá RMSSD, což je jiná statistika, takže tyto dvě hodnoty nemíchejte pod jedním kódem.

## Související

- [Data z nositelných zařízení ve FHIR](https://developers.anpheros.com/cs/guides/wearable-data-fhir): mapovací tabulka a backendový kód
- [Health Connect do FHIR](https://developers.anpheros.com/cs/guides/health-connect-fhir): totéž na Androidu
- [Jak vytvořit aplikaci pro osobní zdravotní záznamy](https://developers.anpheros.com/cs/guides/personal-health-record-app)
- [Jak vytvořit zdravotnickou aplikaci s Flutterem](https://developers.anpheros.com/guides/healthcare-app-flutter)
