Интеграция с 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 и при запрете, и при «ещё не спрашивали». Это защита приватности — по состоянию разрешения нельзя сделать вывод о наличии данных.
Практическое следствие: нельзя показывать алерт «вы не дали доступ к шагам». Надо молча пробовать читать данные, и если массив пустой — показывать нейтральное сообщение «данные недоступны» с кнопкой «Открыть Здоровье».
«HealthKit — это мощный инструмент, но его неправильная интеграция — основная причина отказов в App Store. Используйте минимально необходимые типы данных и всегда добавляйте описания в Info.plist.» — выдержка из рекомендаций Apple для разработчиков.
Почему выбор типа запроса критичен?
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.







