HealthKit у iOS: інтеграція даних здоров'я та тренувань
Ми розробляємо iOS-додатки з інтеграцією HealthKit, і ось з якою реальною проблемою стикаються майже всі клієнти: після першої версії додаток відхиляють в App Store через некоректний запит дозволів або невідповідність Guideline 5.1.1. Близько 30% додатків з HealthKit проходять рев'ю лише з другої спроби. HealthKit — це не просто API читання даних з Apple Watch. Це центральне сховище здоров'я iOS з жорсткою схемою, гранулярними дозволами на кожен тип і суворою політикою HealthKit.
За кілька років практики ми виконали понад 50 інтеграцій HealthKit для клієнтів з різних сфер: фітнес, медицина, страхування. Наші інженери підготували чек-лист, який скорочує час узгодження з Apple в середньому на 2 тижні.
Як рев'ю App Store впливає на інтеграцію HealthKit?
Apple перевіряє HealthKit-інтеграцію вручну при кожному рев'ю. Основні причини відхилення:
- Додаток запитує типи даних, які не використовує (
HKObjectTypeповинні відповідати реальній функціональності). - Немає
NSHealthShareUsageDescription/NSHealthUpdateUsageDescriptionвInfo.plist— банальний crash при першому запиті. - Додаток запитує дозволи на запис тренувань, але сам не є fitness-додатком — відхилення за Privacy (Section 5.1.1).
Особливість дозволів HealthKit: користувач може заборонити доступ до певного типу, але додаток ніколи не дізнається про це явно. Метод HKHealthStore.authorizationStatus(for:) повертає .notDetermined і при забороні, і при «ще не питали». Це захист приватності — за станом дозволу не можна зробити висновок про наявність даних.
Практичний наслідок: не можна показувати алерт «ви не надали доступ до кроків». Треба мовчки пробувати читати дані, і якщо масив порожній — показувати нейтральне повідомлення «дані недоступні» з кнопкою «Відкрити Здоров'я».
Чому вибір типу запиту критичний?
HKSampleQuery підходить для сирих семплів: кожен вимір пульсу, кожен крок. На активному користувачі за рік накопичуються десятки тисяч записів — запит без ліміту і сортування призведе до OutOfMemory. Використовуйте limit і сортування:
let query = HKSampleQuery( sampleType: HKQuantityType(.heartRate), predicate: HKQuery.predicateForSamples( withStart: startDate, end: endDate, options: .strictStartDate ), limit: 1000, sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)] ) { _, samples, error in guard let samples = samples as? [HKQuantitySample] else { return } let bpmValues = samples.map { $0.quantity.doubleValue(for: .init(from: "count/min")) } // обробка } healthStore.execute(query) HKStatisticsQuery обробляє агреговані дані в 10 разів швидше, ніж HKSampleQuery для таких задач, як сума кроків за день. Для отримання статистики за інтервалами (день, тиждень) за період використовуйте HKStatisticsCollectionQuery:
let interval = DateComponents(day: 1) let query = HKStatisticsCollectionQuery( quantityType: HKQuantityType(.stepCount), quantitySamplePredicate: nil, options: .cumulativeSum, anchorDate: Calendar.current.startOfDay(for: Date()), intervalComponents: interval ) query.initialResultsHandler = { _, results, _ in results?.enumerateStatistics(from: startDate, to: endDate) { stat, _ in let steps = stat.sumQuantity()?.doubleValue(for: .count()) ?? 0 } } HKAnchoredObjectQuery — для фонових оновлень: додаток отримує лише дельту з моменту останнього запиту.
| Тип запиту | Призначення | Продуктивність |
|---|---|---|
| HKSampleQuery | Сирі семпли | Середня (обмеження пам'яті) |
| HKStatisticsQuery | Агрегати (сума, середнє) | Висока (в 10 разів швидше) |
| HKAnchoredObjectQuery | Дельта-оновлення | Висока (лише нові дані) |
Як записати тренування: HKWorkoutBuilder в реальному часі
Для запису активної тренування — тільки HKWorkoutBuilder, не старий HKWorkout(activityType:start:end:). Builder дозволяє додавати семпли в реальному часі:
let config = HKWorkoutConfiguration() config.activityType = .running config.locationType = .outdoor let builder = HKWorkoutBuilder(healthStore: healthStore, configuration: config, device: .local()) builder.beginCollection(withStart: Date()) { success, error in // тренування почалося } // кожні 5 секунд додаємо ЧСС let heartRateSample = HKQuantitySample( type: HKQuantityType(.heartRate), quantity: HKQuantity(unit: .init(from: "count/min"), doubleValue: 142), start: Date(), end: Date() ) builder.add([heartRateSample]) { _, _ in } // завершення builder.endCollection(withEnd: Date()) { _, _ in builder.finishWorkout { workout, error in // workout збережено в HealthKit } } Типові помилки при інтеграції HealthKit
- Виклик HealthKit API в MainActor без
async/await— заблокує UI на повільних запитах до великих наборів даних. - Не перевіряти
HKHealthStore.isHealthDataAvailable()— на iPad без Apple Watch HealthKit недоступний. - Читати ЧСС в одиницях
count/minзамістьHKUnit(from: "count/min")— результат буде невірним.
Повний список типів даних HealthKit, з якими ми працюємо
- Кроки (stepCount) та дистанція (distanceWalkingRunning)
- Частота серцевих скорочень (heartRate) та варіабельність (heartRateVariabilitySDNN)
- Енергія спокою та активна енергія (basalEnergyBurned, activeEnergyBurned)
- Сон (sleepAnalysis) — категорії: inBed, asleep, awake
- Вага, зріст, індекс маси тіла
- Глюкоза в крові, артеріальний тиск, кисень в крові
- Тренування (workout) з метаданими: тип, тривалість, калорії
Що входить в роботу: deliverables
- Код інтеграції з читанням та записом потрібних типів даних.
- Екран запиту дозволів з інформаційним текстом.
- Обробка всіх edge-cases (немає даних, заборона, порожні результати).
- Фонова синхронізація з сервером через
HKAnchoredObjectQuery. - Документація по роботі з HealthKit для вашої команди.
- Консультація щодо проходження рев'ю App Store.
Терміни орієнтовно
| Сценарій | Термін |
|---|---|
| Читання кроків, пульсу та тренувань | 5–8 робочих днів |
| Запис тренувань + фонова синхронізація | 2–3 тижні |
| Повний цикл (читання, запис, екран дозволів, деплой) | від 3 тижнів |
Вартість розраховується індивідуально після аналізу вашого проекту. Замовте консультацію — ми оцінимо обсяг робіт і підготуємо комерційну пропозицію. Зв'яжіться з нами, щоб обговорити деталі інтеграції HealthKit у ваш додаток. Гарантуємо проходження рев'ю App Store.







