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.







