← Todos os Posts

HealthKit + SwiftUI no iOS 26: autorização, tipos de amostra e padrões multiplataforma a partir do envio de dois apps

HealthKit é um dos frameworks da Apple mais complicados de implementar corretamente em um app SwiftUI. O fluxo de autorização tem uma armadilha de falha transitória que pode bloquear permanentemente o acesso dos usuários. Os tipos de amostra se dividem de forma desconfortável entre dados quantitativos (HKQuantitySample para consumo de água, passos, calorias) e dados categóricos (HKCategorySample para sessões mindful, sono, fluxo menstrual). A superfície API async exige envolver chamadas baseadas em callback do HealthKit em withCheckedThrowingContinuation. E no watchOS os padrões mudam novamente.

Eu enviei HealthKit em dois apps de produção: Water (rastreamento de consumo de água, HealthKitService com ~192 linhas)1 e Return (registro de sessões mindful, HealthKitManager com ~171 linhas mais um HealthKitPermissionSheet de 155 linhas).2 Juntos eles cobrem ambos os principais formatos de amostra do HealthKit, ambas as direções (leitura + escrita vs. somente escrita) e implantação tanto em plataforma única quanto multiplataforma.

Este texto percorre os padrões que sobreviveram à produção: UX de pré-permissão, o modificador SwiftUI .healthDataAccessRequest vs. a API legada requestAuthorization, o wrapper async para consultas de amostras e os deltas específicos do watchOS.

TL;DR

  • O reporte do status de autorização é assimétrico. A API da Apple informa “compartilhamento autorizado” de forma confiável, mas não informa “leitura negada” por motivos de privacidade. O artigo cobre como detectar “o usuário foi consultado, mas não concedeu” sem inferir o estado de leitura.
  • Dados quantitativos usam HKQuantitySample com HKQuantityType e HKUnit (o Water usa .literUnit(with: .milli) para consumo de água). Dados categóricos usam HKCategorySample com HKCategoryType (o Return usa .mindfulSession).
  • O sheet de pré-permissão é o padrão mais ignorado. O diálogo de permissão do sistema da Apple é estéril; uma View personalizada exibida primeiro explica o valor e melhora drasticamente as taxas de concessão.
  • O HealthKit no watchOS precisa de uma instância separada de HKHealthStore, tem regras mais rigorosas de re-prompt de autorização e não pode mostrar um sheet SwiftUI para UX de pré-permissão.
  • O padrão recordAuthorizationAttempt() no Return impede que falhas transitórias de apresentação sejam tratadas como negação permanente.

Os dois formatos de amostra

O HealthKit divide seu modelo de amostras ao longo de um eixo que afeta cada linha de código que você escreve:3

Formato de amostra Uso típico API
HKQuantitySample água, passos, calorias, massa corporal, frequência cardíaca HKQuantityType + HKUnit + HKQuantity
HKCategorySample sessões mindful, sono, fluxo menstrual, atividade sexual HKCategoryType + HKCategoryValue
HKWorkout exercício estruturado (corrida, natação) HKWorkoutBuilder, HKWorkoutSession

Água é uma quantidade. Código real de produção de HealthKitService.swift:1

import HealthKit

@Observable
final class HealthKitService {
    static let shared = HealthKitService()

    private let healthStore = HKHealthStore()
    private let waterType = HKQuantityType(.dietaryWater)

    func logWater(amount: Double, date: Date = .now) async throws -> UUID {
        guard isAuthorized else { throw HealthKitError.notAuthorized }

        let quantity = HKQuantity(unit: .literUnit(with: .milli), doubleValue: amount)
        let sample = HKQuantitySample(
            type: waterType,
            quantity: quantity,
            start: date,
            end: date,
            metadata: [HKMetadataKeyWasUserEntered: true]
        )

        try await healthStore.save(sample)
        return sample.uuid
    }
}

Três detalhes da produção:

  1. .literUnit(with: .milli) é a unidade canônica para água em mililitros. O HealthKit aceita qualquer unidade (onças fluidas dos EUA, litros), mas o construtor importa porque a Apple normaliza tudo para litros internamente. Escolher .milli permite armazenar valores inteiros (240, 500) em vez de litros fracionados (0,240, 0,500).
  2. HKMetadataKeyWasUserEntered: true sinaliza a amostra como inserida manualmente em vez de medida. O app Saúde mostra um pequeno indicador de “inserido manualmente” nessas amostras; o usuário confia nos dados inseridos manualmente de forma diferente dos dados medidos por balança.
  3. start e end são o mesmo Date para amostras instantâneas. Quantidades acumulam ao longo de uma janela [start, end], mas para “bebi 240ml agora mesmo” a janela colapsa em um ponto.

Uma sessão mindful é categórica. Código real de produção do HealthKitManager.swift do Return:2

import HealthKit

@MainActor
class HealthKitManager {
    static let shared = HealthKitManager()
    let healthStore = HKHealthStore()
    let mindfulType = HKCategoryType(.mindfulSession)

    func saveMindfulSession(start: Date, end: Date) async -> Bool {
        guard isAvailable else { return false }
        guard end > start else { return false }

        let sample = HKCategorySample(
            type: mindfulType,
            value: HKCategoryValue.notApplicable.rawValue,
            start: start,
            end: end
        )
        // ... save via healthStore.save(sample) ...
    }
}

Dois detalhes:

  1. HKCategoryValue.notApplicable.rawValue é o sentinela estrutural. Sessões mindful não têm um “valor” significativo (são marcadores de duração), então o HealthKit exige um valor de categoria sentinela (Int(0)) para que o campo satisfaça o sistema de tipos. Outras amostras de categoria têm valores mais ricos: o sono usa HKCategoryValueSleepAnalysis.asleep, etc.
  2. A janela start/end é real para amostras de categoria. Uma sessão mindful de 10 minutos tem start e end separados por 10 minutos, e a contagem diária de minutos mindful do HealthKit soma essas durações.

O fluxo de autorização (e sua armadilha)

A autorização do HealthKit é propositalmente assimétrica. authorizationStatus(for:) reporta o status de compartilhamento/escrita com sinceridade (.sharingAuthorized, .sharingDenied, .notDetermined), mas a concessão ou negação de leitura não é diretamente observável via essa API. A Apple oculta intencionalmente o estado de leitura para impedir que apps infiram quais dados existem no perfil de Saúde do usuário.4 Você descobre a decisão de leitura indiretamente: as consultas retornam dados se o usuário concedeu leitura, e as consultas retornam resultados vazios se o usuário negou leitura. Não há nenhum sinal de “leitura foi negada” para o seu código ramificar.

Ambos os apps contornam isso de formas diferentes.

O Water lê suas próprias amostras. Como o Water tanto escreve quanto lê entradas de água (para preencher o “histórico de hoje”), seu fluxo de autorização precisa lidar com o caso em que a negação de leitura é invisível:1

private var typesToShare: Set<HKSampleType> { [waterType] }
private var typesToRead: Set<HKSampleType> { [waterType] }

func requestAuthorization() async throws {
    guard isHealthDataAvailable else { throw HealthKitError.notAvailable }

    try await healthStore.requestAuthorization(toShare: typesToShare, read: typesToRead)

    await MainActor.run { checkAuthorizationStatus() }
}

func checkAuthorizationStatus() {
    authorizationStatus = healthStore.authorizationStatus(for: waterType)
    isAuthorized = authorizationStatus == .sharingAuthorized
}

Note o que checkAuthorizationStatus NÃO faz: pedir o status de autorização de leitura. O Water apenas verifica o status de compartilhamento. Se o usuário conceder compartilhamento, mas negar leitura, a UI do Water exibirá “sem entradas” porque a leitura retorna vazia (não por causa de um erro explícito). O Water confia na decisão de compartilhamento e deixa a ausência de dados falar por si. O usuário pode corrigir isso em Configurações se se importar.

O Return apenas escreve. O Return registra sessões mindful, mas nunca as lê de volta; a lista de sessões que ele exibe vem de seu próprio NSUbiquitousKeyValueStore, não do HealthKit. Então a solicitação de autorização do Return é apenas de escrita:2

func requestAuthorization() async -> Bool {
    guard isAvailable else { return false }

    do {
        try await healthStore.requestAuthorization(
            toShare: [mindfulType],
            read: []  // We only need write access
        )
        hasRequestedHealthKit = authorizationStatus != .notDetermined
        return isAuthorizedToWrite()
    } catch {
        hasRequestedHealthKit = authorizationStatus != .notDetermined
        return false
    }
}

O conjunto vazio read: [] é intencional. Pedir acesso de leitura que você não precisa expande o escopo de permissão que você tem que justificar na Revisão da App Store e confunde usuários que veem “Return quer ler suas sessões mindful” quando o app obviamente não precisa disso.

A armadilha. Ambos os apps convergiram para o mesmo padrão defensivo: marcar uma tentativa de autorização como “concluída” apenas se o status realmente sair de .notDetermined. O código ingênuo é:

hasRequestedHealthKit = true  // ❌ wrong: treats transient failures as denial

O padrão correto do Return:2

hasRequestedHealthKit = authorizationStatus != .notDetermined  // ✓ checks real state

Por que isso importa: o modificador SwiftUI .healthDataAccessRequest e a API subjacente requestAuthorization podem falhar em apresentar o diálogo do sistema sob certas condições (conflitos de sheet, interrupções no ciclo de vida da view, estado transitório do SO). Se você marcar a tentativa como “concluída” antes de verificar o status real, você prende os usuários em um estado em que seu app pensa que eles recusaram, mas nenhum diálogo do sistema apareceu. Eles não têm caminho de volta a menos que vão em Configurações → Privacidade → Saúde e concedam manualmente, o que eles não pensarão em fazer porque nunca viram seu prompt. O recordAuthorizationAttempt() do Return existe especificamente para esse caso.

O sheet de pré-permissão

O diálogo de permissão do HealthKit da Apple é correto, mas não vendido. Ele mostra uma lista de tipos que seu app quer compartilhar ou ler, com toggles. Não há contexto sobre por que o app quer os dados, sem explicação de benefícios, sem marca do app. Os usuários tocam em Não Permitir porque o prompt está descontextualizado.

O Return entrega um HealthKitPermissionSheet que aparece antes do diálogo do sistema. O sheet mostra o ícone do app Return ao lado do ícone do Apple Saúde (correto para a HIG: o ícone do Apple Saúde não pode ser cortado ou sombreado),5 declara o benefício (“Acompanhe sua prática” / “Salve suas sessões de meditação como Minutos Mindful no Apple Saúde”), lista três linhas de benefícios (“Veja sua prática no Apple Saúde”, “Sincroniza em todos os seus dispositivos”, “Funciona com outros apps de bem-estar”), e termina em um único botão de avanço Continue que aciona a solicitação do sistema. Estrutura real de HealthKitPermissionSheet.swift:6

struct HealthKitPermissionSheet: View {
    var onEnableRequested: () -> Void
    var theme: Theme

    var body: some View {
        VStack(spacing: 0) {
            HStack(spacing: 16) {
                Image("ReturnAppIcon")
                    .resizable().scaledToFit().frame(width: 80, height: 80)
                    .clipShape(RoundedRectangle(cornerRadius: 18))

                Text("+").font(.title)

                Image("AppleHealthIcon")
                    .resizable().scaledToFit().frame(width: 80, height: 80)
                    // No clipShape; Apple HIG forbids altering the Health icon
            }

            // Title + subtitle + benefits list

            // (See discussion below for the production comment.)
            Button { onEnableRequested() } label: {
                Text("Continue")
            }
        }
        .interactiveDismissDisabled(true)
    }
}

O interactiveDismissDisabled(true) mais a ausência de qualquer botão de cancelamento é uma escolha de design deliberada. A Diretriz 5.1.1 de Revisão da App Store da Apple exige que apps respeitem as configurações de privacidade do usuário e proíbe manipular, enganar ou forçar consentimento.10 O comentário do código de produção acima do botão Continue diz:

Single forward action: the system HealthKit dialog owns the real yes/no choice. Apple Guideline 5.1.1(iv): the priming screen may not include any exit/dismiss path that bypasses the system permission request.

Esse enquadramento é mais rigoroso do que o texto literal da diretriz (que fala sobre respeitar o consentimento e não forçá-lo, mas não prescreve UX de tela de priming nessas palavras). É a interpretação do Return, codificada no código-fonte. A intenção: um usuário que recusa deve fazê-lo na tela da Apple, não na do Return. O resultado é um sheet com uma única ação de avanço e sem rota de fuga. O texto e as linhas de benefício precisam conquistar o toque; não há ramificação “vou pensar”.

O fluxo:

  1. O usuário toca em “Conectar Saúde” nas configurações do Return.
  2. O sheet de pré-permissão aparece. O usuário lê a explicação.
  3. O usuário toca em Continuar. O sheet permanece montado enquanto requestAuthorization é executado e o diálogo do sistema aparece.
  4. O usuário aceita (ou nega) no diálogo do sistema. O Return chama recordAuthorizationAttempt() para capturar o resultado e o sheet é dispensado.

Por que se preocupar. A Apple não publicou números oficiais sobre o aumento na taxa de concessão a partir de sheets de pré-permissão, mas todo desenvolvedor iOS com quem conversei que tinha um teste A/B e a paciência para executá-lo relatou a mesma direção: sheets de pré-permissão aumentam dramaticamente a taxa de concessão de autorização de compartilhamento. O padrão agora é comum o suficiente para que os próprios templates da Apple (Fotos, Câmera, Localização) cada vez mais incluam sua própria UX de pré-permissão.

A variante para watchOS

O HealthKit no watchOS compartilha a mesma superfície de API que o HealthKit no iOS (HKHealthStore, tipos de amostra, autorização), mas com três deltas estruturais:

  1. Um novo HKHealthStore por app de relógio. O app do relógio e o app do iPhone pareado têm cada um sua própria instância de HKHealthStore. Ambos podem escrever no banco de dados HealthKit do usuário, ambos podem ler suas próprias amostras. A store não é compartilhada entre o par.
  2. Sem sheets SwiftUI para pré-permissão. As hierarquias de view do watchOS não suportam sheets da forma como o iOS suporta. A UX de pré-permissão tem que ser uma tela cheia.
  3. Regras mais rigorosas de re-prompt. A chamada requestAuthorization do watchOS é mais conservadora ao reapresentar o diálogo do sistema se o usuário tiver recusado anteriormente; você pode precisar direcionar os usuários para o app Watch no iPhone para alterar a configuração, já que o próprio relógio não tem UI de Configurações → Privacidade → Saúde.

Código real de produção de WatchHealthKitManager.swift:7

@MainActor
class WatchHealthKitManager {
    static let shared = WatchHealthKitManager()
    let healthStore = HKHealthStore()
    let mindfulType = HKCategoryType(.mindfulSession)

    private init() {}

    var isAvailable: Bool { HKHealthStore.isHealthDataAvailable() }

    /// Returns true if the system request completed (success or already-authorized).
    /// Caller checks isAuthorizedToWrite() separately for the actual share state.
    func requestAuthorization() async -> Bool {
        guard isAvailable else { return false }
        do {
            try await healthStore.requestAuthorization(toShare: [mindfulType], read: [])
            return true
        } catch {
            return false
        }
    }

    func isAuthorizedToWrite() -> Bool {
        guard isAvailable else { return false }
        return healthStore.authorizationStatus(for: mindfulType) == .sharingAuthorized
    }
    // ... saveMindfulSession identical to iOS variant ...
}

A divisão é deliberada: requestAuthorization reporta se a chamada do sistema foi bem-sucedida, e isAuthorizedToWrite reporta o resultado que o usuário escolheu. Dividir esses no relógio torna o código mais fácil de raciocinar; no iOS a divisão equivalente aparece como o par recordAuthorizationAttempt() mais isAuthorizedToWrite() no HealthKitManager.

A classe Watch tem aproximadamente metade do tamanho da iOS porque ela não precisa de:

  • A flag UserDefaults hasRequestedHealthKit (a UX do relógio tem menos caminhos de segunda tentativa para suportar).
  • O encanamento do HealthKitPermissionSheet (sem UI de sheet no watchOS).
  • O método recordAuthorizationAttempt() (o fluxo mais estreito do relógio tem menos casos extremos de falha transitória).

A contrapartida é que o app watchOS às vezes atinge um estado de negado-sem-recurso para usuários que recusaram o diálogo do sistema e não percebem que podem corrigi-lo a partir do app Watch no iPhone. O Return mostra uma pequena instrução in-app neste caso (“Abra o app Watch no iPhone → Meu Watch → Privacidade → Saúde”) em vez de tentar re-promptar.

O que eu construiria de forma diferente

Três lições do envio de HealthKit em dois apps de produção.

Ambas as APIs funcionam; a escolha depende do contexto de apresentação. O modificador SwiftUI .healthDataAccessRequest envolve a API legada em uma forma mais declarativa e lida corretamente com o contexto de apresentação no iPadOS. O Return usa o modificador, expondo seus tipos de compartilhamento via uma propriedade pública mindfulShareTypes em HealthKitManager para que uma view pai SwiftUI possa conectá-lo. O Water usa a healthStore.requestAuthorization legada diretamente porque o fluxo de autorização do Water é executado a partir de um contexto não-View (um serviço @Observable). A divisão é um padrão útil: prefira o modificador quando a solicitação se origina de um evento do ciclo de vida do SwiftUI (toque em botão dentro de um sheet), recorra à API legada quando a solicitação se origina de um serviço.

Sheets de pré-permissão valem o custo de engenharia no iOS, não no watchOS. O sheet de pré-permissão adiciona talvez quatro horas de trabalho (view do sheet, texto, tematização, integração). O aumento na taxa de concessão no iOS é grande o suficiente para que as quatro horas sejam um investimento óbvio. No watchOS, a pré-permissão equivalente em tela cheia é mais intrusiva (toma toda a tela do relógio em vez de ser um sheet), o usuário tem menos probabilidade de ler textos longos em uma tela pequena, e o fluxo de UX do relógio tem menos pontos de entrada onde o usuário está pedindo um recurso que requer HealthKit. Eu enviei o Return sem um no watchOS e não me arrependi.

Acompanhe hasRequestedHealthKit separadamente do status de autorização ao vivo. A API do HealthKit informa o status atual de autorização, mas não informa se você já perguntou. A distinção importa porque o comportamento correto do segundo toque depende disso: o primeiro toque deve chamar requestAuthorization; o segundo toque, se o usuário recusou anteriormente, deve mostrar um alerta “Configurações → Privacidade → Saúde” em vez de re-chamar a API (que silenciosamente não faz nada em um estado negado). A flag UserDefaults hasRequestedHealthKit é o que torna o segundo toque útil.

Quando não usar HealthKit

A recusa é parte do design.

Não escreva no HealthKit só porque você pode. Um app de timer de foco não precisa escrever um treino. Um app de anotações não precisa registrar mindfulness. Adicionar HealthKit porque é “integração grátis” expande sua pegada de privacidade, seu atrito de autorização e o escopo do questionário da Revisão da App Store sem dar ao usuário valor material.

Não leia do HealthKit se puder evitar. O acesso de leitura é mais difícil de justificar na Revisão da App Store e mais difícil de explicar aos usuários. Muitos apps que leem do HealthKit poderiam apenas escrever e deixar os usuários verem seus dados no Apple Saúde; o fluxo de leitura dobra a superfície para um ganho de UX insignificante.

Não use HealthKit no Mac para dados exclusivamente entre dispositivos. O macOS suporta HealthKit desde o macOS 13, mas a maioria dos dados do Saúde se origina no iPhone ou Apple Watch. Se seu app Mac precisa dos mesmos dados, escreva no HealthKit no iPhone e deixe a sincronização entre dispositivos da Apple expô-lo no Mac. Escritas diretas no HealthKit a partir do Mac são válidas, mas raras na prática.

Não envie sem testar o caminho de negado-depois-revogado. Os usuários concedem permissão e depois a revogam em Configurações → Privacidade → Saúde. Seu app precisa lidar com a revogação de forma elegante, geralmente mostrando a instrução de deep-link de Configurações na próxima vez que tentarem usar o recurso. Tanto o Water quanto o Return enviam esse caminho; nenhum deles acertou na primeira tentativa.

O que isso significa para apps SwiftUI enviando HealthKit no iOS 26+

Três pontos a destacar.

  1. Decida apenas-escrita vs. leitura+escrita antes de projetar a UI. Apenas-escrita é uma superfície menor e uma Revisão da App Store mais rápida. Leitura+escrita é mais flexível, mas adiciona a assimetria de “negação de leitura é invisível”.
  2. Envie um sheet de pré-permissão no iOS. O aumento na taxa de concessão é real. Use o ícone da Apple corretamente (sem cortes, sem sombra), declare o benefício, depois chame a API do sistema.
  3. Trate o HealthKit do watchOS como uma variante menor e mais simples do padrão iOS. Menos cerimônia, sem sheets, autorização de propósito único. Direcione os usuários para o app Watch no iPhone para reconceder.

Combine este post com meus textos anteriores para a mesma família de apps: App Intents tipados para Apple Intelligence; servidores MCP para agentes cross-LLM; padrões Liquid Glass para a camada visual; envio multiplataforma para alcance entre dispositivos. O HealthKit é a camada de fonte de dados, situada sob a camada visual e as superfícies de integração.8

FAQ

Posso compartilhar autorização entre um app iOS e sua extensão watchOS?

Não. O HKHealthStore do iOS e o HKHealthStore do watchOS são independentes. O usuário concede autorização separadamente em cada plataforma via diálogos do sistema separados. Seu código em cada lado verifica seu próprio status de autorização; você não pode ler o status do iOS a partir do relógio ou vice-versa.

O que acontece com minhas amostras se o usuário revogar o acesso de escrita?

As amostras existentes permanecem no HealthKit. O usuário pode excluí-las manualmente do app Saúde se quiser, mas revogar o acesso do seu app apenas impede novas escritas. Seu app não pode mais salvar ou modificar amostras, mas os dados históricos do usuário são preservados.

O modificador SwiftUI .healthDataAccessRequest é seguro de usar em produção?

Funciona no iOS 17.4+ e foi refinado em lançamentos subsequentes. O Return usa o modificador (ele expõe mindfulShareTypes em HealthKitManager para o SwiftUI consumir). O Water usa healthStore.requestAuthorization legada diretamente porque a solicitação do Water se origina de um serviço @Observable não-View. Escolha com base em onde a solicitação é iniciada: evento do ciclo de vida do SwiftUI → modificador; serviço ou contexto não-View → API legada.

Por que o status de autorização do HealthKit diz .sharingAuthorized mesmo quando nunca pedi acesso de compartilhamento?

Não diz. O status é por HKObjectType. Se você verificar authorizationStatus(for: heartRateType) e nunca tiver solicitado frequência cardíaca, você obterá .notDetermined. O status só vai para .sharingAuthorized após uma autorização bem-sucedida para esse tipo específico.

Preciso de um manifesto de privacidade para o HealthKit?

Sim. Apps que tocam o HealthKit precisam declarar o uso em PrivacyInfo.xcprivacy (o manifesto de privacidade) e no questionário de privacidade do App Store Connect. As entradas relevantes são NSHealthShareUsageDescription e NSHealthUpdateUsageDescription no Info.plist, mais as declarações correspondentes no manifesto de privacidade.9

Referências


  1. Código de produção em Water/Water/Services/HealthKitService.swift (192 linhas). Water do autor, um app SwiftUI de rastreamento de água disponível no iOS, iPadOS, macOS, watchOS e visionOS. Usa HKQuantitySample com HKQuantityType(.dietaryWater) e a flag HKMetadataKeyWasUserEntered

  2. Código de produção em Return/Return/HealthKitManager.swift (171 linhas). Return do autor, um app SwiftUI de timer de meditação disponível no iOS, iPadOS, macOS, watchOS e tvOS. Usa HKCategorySample com HKCategoryType(.mindfulSession) e HKCategoryValue.notApplicable.rawValue

  3. Apple Developer, “HealthKit framework”. Os dois principais tipos de amostra do framework são HKQuantitySample (para quantidades mensuráveis como água, passos, calorias) e HKCategorySample (para eventos não-quantitativos como sessões mindful, sono, fluxo menstrual). HKWorkout cobre exercício estruturado. 

  4. Apple Developer, “Authorizing access to health data”. A Apple oculta intencionalmente o estado de negação de leitura para impedir que apps infiram quais dados existem no perfil de Saúde do usuário. O método authorizationStatus(for:) retorna apenas resultados honestos para acesso de compartilhamento. 

  5. Apple Developer, “Apple Health icon usage” Human Interface Guidelines. O ícone do Saúde da Apple não pode ser modificado, cortado, sombreado ou recolorido; reproduza-o em fidelidade 1:1 em UIs promocionais e de pré-permissão. 

  6. Código de produção em Return/Return/HealthKitPermissionSheet.swift (155 linhas). View de pré-permissão exibida antes de acionar o diálogo HealthKit do sistema. Combina o ícone do app Return com o ícone do Apple Saúde, explica o benefício e aciona a autorização via uma callback closure no toque do usuário. 

  7. Código de produção em Return/ReturnWatch Watch App/WatchHealthKitManager.swift (86 linhas). A variante watchOS do HealthKitManager. HKHealthStore independente, sem flag hasRequestedHealthKit, sem encanamento de sheet de permissão. 

  8. Análise do autor: o HealthKit é a camada de fonte de dados de um app iOS, App Intents são a superfície de IA do sistema, MCP é a superfície de agente cross-LLM, Liquid Glass é a superfície visual. As quatro camadas se compõem em um único produto enviado em todas as cinco plataformas Apple. 

  9. Apple Developer, “Privacy manifest files”. O uso do HealthKit deve ser declarado em PrivacyInfo.xcprivacy mais as chaves NSHealthShareUsageDescription e NSHealthUpdateUsageDescription no Info.plist

  10. Apple Developer, “App Review Guideline 5.1.1”. Os apps devem respeitar as configurações de privacidade do usuário, solicitar consentimento antes de coletar dados pessoais e não podem manipular, enganar ou forçar o consentimento. A formulação exata sobre caminhos de saída de tela de priming neste artigo reflete a interpretação do Return em vez do texto literal da diretriz. 

Artigos relacionados

Liquid Glass in SwiftUI: Three Patterns From Shipping Return on iOS 26

Apple's Liquid Glass is a one-line SwiftUI API. Three patterns from Return go beyond .glassEffect(): glass on text via C…

17 min de leitura

Five Apple Platforms, Three Shared Files: How Return Actually Ships Cross-Platform SwiftUI

Return runs on iPhone, iPad, Mac, Apple Watch, and Apple TV. Three Swift files are shared across all five targets out of…

18 min de leitura

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 min de leitura