# Apple Health (HealthKit) para FHIR

> Leia dados do Apple Watch e do Apple Health com HealthKit em Swift, por dia local, e escreva-os num registo FHIR R4: permissões, sincronização em segundo plano, regras da Apple.

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

**Os dados do Apple Watch residem no Apple Health no iPhone emparelhado, e a única forma de os ler é através do HealthKit, a partir de uma aplicação nesse iPhone, com a permissão da pessoa.** Para os colocar num registo FHIR, leia estatísticas diárias com `HKStatisticsCollectionQuery`, envie os valores para o seu backend e escreva cada métrica como uma Observação com um código LOINC e uma unidade UCUM. Esta página mostra o código Swift (verificado em termos de tipo contra o SDK do iOS 17), as permissões e regras definidas pela Apple, e como os valores se tornam Observações FHIR R4.

## O que está no Apple Health

O Apple Health recolhe o que o iPhone e o Apple Watch medem — frequência cardíaca, frequência cardíaca em repouso, variabilidade da frequência cardíaca (SDNN), oxigénio no sangue, frequência respiratória, passos, energia, fases do sono, notificações de ritmo irregular, gravações de ECG — e o que outras aplicações escrevem: Garmin Connect, Oura, Withings Health Mate, balanças inteligentes, monitores de pressão arterial, medidores de glicose. Ler o Apple Health, portanto, abrange mais do que o Apple Watch.

Não existe um servidor HealthKit ou API web. Os dados permanecem no dispositivo (e na cópia de segurança encriptada do iCloud da pessoa); a sua aplicação lê-os localmente.

## Permissões

1. Ative a capacidade **HealthKit** no Xcode e adicione `NSHealthShareUsageDescription` a `Info.plist` (mais `NSHealthUpdateUsageDescription` apenas se escrever).
2. Solicite os tipos de que necessita. As pessoas podem permitir alguns e recusar outros, e o **HealthKit não informa a sua aplicação se o acesso de leitura foi recusado**: um tipo recusado simplesmente não retorna dados. Desenhe os ecrãs para "sem dados" em vez de para um erro.
3. Solicite no momento em que a pessoa se conecta, com uma frase explicando o porquê, não no primeiro lançamento.

## Ler valores diários em Swift

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

Porquê consultas de estatísticas em vez de ler amostras: `HKStatisticsCollectionQuery` devolve totais e médias por dia que a Apple Health já desduplicou entre fontes, pelo que os passos contados tanto pelo iPhone como pelo Watch não são adicionados duas vezes. Ler amostras brutas e somá-las você mesmo é a fonte mais comum de contagens de passos inflacionadas.

Os dias são os dias de calendário locais da pessoa (`Calendar.current`). Mantenha-os assim até ao registo FHIR, onde o `effectivePeriod` da Observação é esse dia local com o seu deslocamento de fuso horário.

## Manter o registo atualizado

- **Ao abrir:** leia os dias desde a última sincronização bem-sucedida cada vez que a aplicação passa para o primeiro plano. Esta é a base fiável.
- **Em segundo plano:** `HKObserverQuery` com `enableBackgroundDelivery(for:frequency:)` acorda a sua aplicação quando chegam novos dados; necessita da autorização de entrega em segundo plano do HealthKit, e o iOS decide o momento exato.
- **Primeira ligação:** importe um histórico limitado (por exemplo, 30 dias) em vez de anos, e depois avance.

## De valores Swift para Observações FHIR

Envie o array `DailyValue` para o seu backend e escreva uma Observação por pessoa, métrica e dia com um identificador estável, atualizando-a quando o mesmo dia voltar a ocorrer. A tabela de mapeamento (tipo HealthKit → LOINC → UCUM), um exemplo JSON validado e o código TypeScript que realiza este upsert, executado na plataforma, encontram-se em [Wearable data in FHIR](https://developers.anpheros.com/pt/guides/wearable-data-fhir). Os códigos para as duas métricas aqui são:

| HealthKit | LOINC | UCUM | Valor por dia |
|---|---|---|---|
| `heartRate` | 8867-4 Heart rate | `/min` | média, com mínimo e máximo como componentes |
| `stepCount` | 41950-7 Number of steps in 24 hour | `{steps}` | total |

## Regras da Apple para dados de saúde

- Diretriz de Revisão de Apps 5.1.3: dados de saúde não podem ser usados para publicidade ou mineração de dados, não podem ser partilhados com terceiros sem o consentimento da pessoa, e informações de saúde pessoais não podem ser armazenadas no iCloud.
- A sua política de privacidade deve indicar o que lê e porquê; a Apple verifica.
- Os dados escritos pela sua app para a Apple Health são atribuídos à sua app; os dados que lê mantêm a sua origem original (`HKSource`), que deve ser incluída no registo como o sistema de origem.

## Registos de Saúde da Apple

Separadamente dos dados de fitness, o Apple Health pode conter registos clínicos descarregados de sistemas de saúde participantes (principalmente nos Estados Unidos), e o HealthKit expõe-nos como objetos `HKClinicalRecord` que transportam o recurso FHIR original. A sua leitura requer permissão e direito próprios. São uma integração diferente dos dados de wearables, e o Anpheros Daily não os lê atualmente.

## Onde o Anpheros se encaixa

A Plataforma Anpheros armazena o resultado: o registo FHIR R4 da pessoa, com cada valor de wearable como uma Observação marcada como dados do dispositivo, consentimento para outras aplicações, proveniência e um registo de acesso. Não lê o Apple Health diretamente — isso acontece na sua aplicação iOS. A aplicação própria do Anpheros, **Anpheros Daily**, lê o Apple Health no iPhone (planos Plus e Max) e escreve resumos diários no registo com os códigos acima.

## Perguntas Frequentes

### Posso ler dados do Apple Watch a partir de um servidor?
Não. Os dados do Apple Watch são sincronizados com o Apple Health no iPhone emparelhado, e o HealthKit só pode ser utilizado por uma aplicação nesse dispositivo. A aplicação lê os dados e envia-os para o seu servidor.

### Existe uma API web ou REST para o Apple Health?
Não. A Apple não oferece uma API web ou REST para o Apple Health: o HealthKit corre apenas dentro de uma aplicação no iPhone (ou Apple Watch) da pessoa. Para utilizar os dados num servidor, a sua aplicação lê-os com a permissão da pessoa e envia-os, por exemplo, como Observações FHIR para o Anpheros.

### Preciso de uma chave de API ou de pagar pela API do Apple Health?
Sem chave e sem taxa: o HealthKit faz parte do iOS. Precisa da capacidade HealthKit na sua aplicação, uma descrição de uso para cada tipo de dados e a permissão da pessoa; a revisão da App Store verifica como utiliza os dados.

### Como sei se a pessoa recusou o acesso a um tipo do HealthKit?
Não pode, para acesso de leitura: o HealthKit esconde-o para proteger a privacidade, e um tipo recusado não devolve dados. Trate "sem dados" como um estado normal e ofereça uma forma de rever as permissões na aplicação Health.

### Porque é que as minhas contagens de passos são mais altas do que na aplicação Health?
Provavelmente está a somar amostras brutas de várias fontes (iPhone e Watch). Utilize `HKStatisticsCollectionQuery` com `.cumulativeSum`, que aplica a própria desduplicação do Apple Health.

### Qual é o código LOINC para a variabilidade da frequência cardíaca do Apple Watch?
O Apple Health armazena HRV como SDNN, que corresponde ao LOINC 80404-7. O Health Connect armazena RMSSD, uma estatística diferente, pelo que não misture as duas sob um único código.

## Relacionado

- [Dados de wearables em FHIR](https://developers.anpheros.com/pt/guides/wearable-data-fhir): a tabela de mapeamento e o código de backend
- [Health Connect para FHIR](https://developers.anpheros.com/pt/guides/health-connect-fhir): o mesmo no Android
- [Como criar uma aplicação de registo de saúde pessoal](https://developers.anpheros.com/pt/guides/personal-health-record-app)
- [Como criar uma aplicação de saúde com Flutter](https://developers.anpheros.com/guides/healthcare-app-flutter)
