Работа с HealthKit. Часть 2

от автора

Конец и начало года у разработчиков, как правило, всегда наполнены большим количеством проектов. Разобравшись со срочными делами и закатав повыше рукава, мы в Techmas пообещали себе делиться еще бОльшим количеством своих разработок с коллегами.

Несмотря на растущую популярность приложений, которые уже используют HealthKit, спрос на мобильные решения для оценки состояния здоровья продолжает развиваться.

Для пояснения всех основных принципов работы c платформой, мы решили вернуться к примеру из прошлой публикации и дополнить его работой с выборками данных в Health.

Введение

Напомним, ранее мы сделали обзор общего функционала HealthKit, рассмотрели приложение для аутентификации в Health и вывода характеристик (characteristics) пользователя. Сейчас мы разберемся с выборками (samples) для чтения и записи новых данных по тренировкам.

Выборки (samples) отличаются от характеристик (characteristics) тем, что они меняются с течением времени и зависят от поведения пользователя. Например, выборки используются для добавления новых данных по тренировкам, их визуализации, определения и расчета дополнительных параметров.

В примере мы покажем как считывать данные по росту и весу пользователя из приложения Health. Далее по ним рассчитаем показатель BMI (индекс массы тела) и добавим полученное значение для отслеживания динамики его изменения.

Итак, вернемся к приложению из предыдущей части. Его код находится здесь.

Подготовка выборки

Создадим тестовые данные для выборки в приложение Health.

Для этого выберем на закладке Body Measurements пункт Weight и внесем несколько ключевых точек с информацией о весе (weight) через Add Data Point.

Данные можно вводить какие угодно и сколько угодно за разные промежутки времени.

Теперь получим разрешение работы с параметрами выборки. Добавим в функцию авторизации authorizeHealthKit() (отдельно мы говорили об авторизации ранее):

let healthKitTypesToWrite = Set(arrayLiteral: HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)!,     HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned)!,     HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)! ) 

Чтение выборки из Health

В нашем примере создадим функцию readMostRecentSample(), которая будет считывать показатели по дате и типу.

Для получения выборки необходимо использовать подкласс HKSampleQuery, который наследуется от HKQuery. По сути, он работает аналогично NSFetchedRequest в Core Data.

При формировании запроса доступны параметры:
1. Тип выборки (например, вес или рост), Type.
2. Условия выделения выборки (период, значения, пр.), NSPredicate.
3. Метод сортировки, NSSortDescriptors.

Второй и третий параметры задаются опционально. После формирования запроса необходимо выполнить executeQuery() для вывода его результата.

В нашем примере создадим метод получения последнего значения для указанного типа выборки. Добавим следующий код в функцию readMostRecentSample():

// 1. Подготовим параметры периода let past = NSDate.distantPast() let now = NSDate() let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)  // 2. Зададим значение сортировки в обратном порядке  let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)  // 3. Ограничим вывод одним значением let limit = 1  // 4. Выполним построение запроса let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescriptor])     { (sampleQuery, results, error ) -> Void in                  if let queryError = error {             completion(nil,error)             return;         }                  // Выделим крайнее значение         let mostRecentSample = results!.first as? HKQuantitySample                  if completion != nil {             completion(mostRecentSample,nil)         } }  // 5. Выполним сам запрос self.healthKitStore.executeQuery(sampleQuery) 

Наша функция позволяет получать последние данные по выборкам определенного типа. Для простоты, вызов readMostRecentSample() добавим в метод viewDidLoad():

// 1. Подготовка параметра HKSampleType для определения веса let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)  // 2. Вызов функции для выделения крайнего значения self.readMostRecentSample(sampleType!, completion: { (mostRecentWeight, error) -> Void in          if( error != nil )     {         print("Error reading weight from HealthKit Store: \(error.localizedDescription)")         return;     } 

Здесь мы используем quantityTypeForIdentifier для определения необходимой выборки, в нашем случае это HKQuantityTypeIdentifierBodyMass.

Расчет значения BMI

Теперь создадим набор для расчета и записи BMI. Он будет рассчитываться по формуле:

bmi = weight / height ^ 2 

Как было показано выше, выделяем значение веса (weight) из Health. Таким же образом мы получим рост (height) пользователя (заменив тип данных и формат, используем HKQuantityTypeIdentifierHeight).

Здесь нам понадобится объект HKQuantitySample. Также необходимо указать:

• Тип объекта HKQuantityType для сохранения. В нашем случае это HKQuantityTypeIdentifierBodyMassIndex.
• Объект HKQuantity. Он инициализируется с передаваемым значением из параметра bmi. Важно, что для преобразования скалярного типа Double используется HKUnit.countUnit(), который позволяет конвертировать типы в необходимые единицы измерения.

Тогда расчет BMI будет выглядеть следующим образом:

var weight: HKQuantitySample var weightLocalizedString = “empty"  weight = (mostRecentWeight as? HKQuantitySample)!; kilograms = weight.quantity.doubleValueForUnit(HKUnit.gramUnitWithMetricPrefix(.Kilo)) let weightFormatter = NSMassFormatter() weightFormatter.forPersonMassUse = true; weightLocalizedString = weightFormatter.stringFromKilograms(kilograms)  print(weightLocalizedString)  let weightInKilograms = kilograms let heightInMeters: Double = 180  let bmi  = weightInKilograms / heightInMeters * heightInMeters  print(String(format: "%.02f", bmi)) 

Также отметим использование форматирование результатов с помощью NSMassFormatter. Сам NSMassFormater, в сущности, не является частью HelathKit, но позволяет работать с типами данных Health. В частности, если в приложение используются килограммы, а устройство не использует метрическую систему, мы имеем возможность привести единицы измерения к нужному виду.

Мы не будем останавливаться на вопросах интерфейса, поэтому результаты выведем в консоль.

Добавление новой выборки в Health

Наконец, для записи полученного значения BMI в HelathKit создадим метод saveBMISample(bmi:Double, date:NSDate). Выходные параметры: само значение BMI и дата его регистрации.

// 1. Создадим выборку BMI let bmiType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex) let bmiQuantity = HKQuantity(unit: HKUnit.countUnit(), doubleValue: bmi) let bmiSample = HKQuantitySample(type: bmiType, quantity: bmiQuantity, startDate: date, endDate: date)  // 2. Сохраним выборку в Health healthKitStore.saveObject(bmiSample, withCompletion: { (success, error) -> Void in if( error != nil ) {   println("Error saving BMI sample: \(error.localizedDescription)") } else {   println("BMI sample saved successfully!") } }) 

Новое значение BMI доступно как для стандартного просмотра, так и может быть использовано сторонним авторизованным приложением.

Примечание

На практике все методы для работы c HealthKit имеет смысл вынести в отдельный класс.
Для нашего примера мы ограничились лишь демонстрацией ключевых этапов работы с платформой.

Код конечного приложения находится здесь.

ссылка на оригинал статьи https://habrahabr.ru/post/276429/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *