Статьи

Начало работы с HealthKit: часть 2

В первой части этого руководства я познакомил вас со структурой HealthKit. Основываясь на своем собственном опыте интеграции HealthKit в одно из моих приложений, я указал на несколько вещей, которые важно иметь в виду. Мы также начали работу над нашим примером приложения HealthBasics , в котором будут объяснены основные принципы работы с HealthKit.

В первой части мы реализовали класс GSHealthKitManager , который мы будем использовать для взаимодействия с HealthKit. Давайте теперь используем класс GSHealthKitManager для реализации функциональности первого контроллера представления примера приложения.

В Project Navigator откройте FirstViewController.m и замените его содержимое следующим:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#import «FirstViewController.h»
#import «GSHealthKitManager.h»
 
@interface FirstViewController ()
 
@property (nonatomic, weak) IBOutlet UILabel *ageLabel;
@property (nonatomic, weak) IBOutlet UITextField *weightTextField;
 
@end
 
 
@implementation FirstViewController
 
— (IBAction)healthIntegrationButtonSwitched:(UISwitch *)sender {
     
    if (sender.isOn) {
        [[GSHealthKitManager sharedManager] requestAuthorization];
    } else {
        // Possibly disable HealthKit functionality in your app.
    }
}
 
— (IBAction)readAgeButtonPressed:(id)sender {
     
    NSDate *birthDate = [[GSHealthKitManager sharedManager] readBirthDate];
     
    if (birthDate == nil) {
        // Either user didn’t set the date, or an error occured.
        return;
    }
     
    NSDateComponents *ageComponents = [[NSCalendar currentCalendar]
                                       components:NSCalendarUnitYear
                                       fromDate:birthDate
                                       toDate:[NSDate date]
                                       options:0];
     
    self.ageLabel.text = [@(ageComponents.year) stringValue];
}
 
— (IBAction)writeWeightButtonPressed:(id)sender {
    [[GSHealthKitManager sharedManager] writeWeightSample:self.weightTextField.text.floatValue];
}
 
@end

Если у вас есть некоторый опыт разработки для iOS, то реализация не должна быть трудной для понимания. В первом контроллере представления мы отвечаем пользователю, переключающему переключатель и нажимающему одну из кнопок. Каждое из этих взаимодействий вызывает метод класса GSHealthKitManager .

Есть причина, по которой я решил использовать переключатель, чтобы запросить у пользователя разрешение на доступ к его данным HealthKit. Как только вы поймете реализацию, вы поймете, что это гораздо лучшее решение.

Пользователю легко понять, что при включении приложение интегрируется с HealthKit. Когда он выключен, это не так. Кроме того, при первом включении этого переключателя пользователю будет предложено предоставить доступ к типам данных работоспособности, которые будет использовать приложение. Это, опять же, хороший пользовательский опыт, потому что пользователь понимает, почему ему предлагается, и какие преимущества он получает, разрешая доступ.

В Project Navigator откройте Main.storyboard . В первой сцене выберите переключатель. На панели « Утилиты» справа откройте Инспектор соединений и в разделе « Отправленные события » перетащите курсор из значения «Изменено» в контроллер « Первое представление» в структуре документа . healthIntegrationButtonSwitched: всплывающем меню, в котором перечислены действия контроллера представления, выберите healthIntegrationButtonSwitched: Это гарантирует, что healthIntegrationButtonSwitched: метод вызывается при каждом переключении переключателя.

Пользовательский интерфейс - подключение розеток 1

Шаги для подключения кнопок Read и Write практически идентичны. Нажмите кнопку « Чтение» , только на этот раз перетащите из события « Touch Up Inside» в контроллер первого вида. Выберите действие readAgeButtonPressed: из всплывающего меню.

Нажмите кнопку « Запись» и перетащите из события « Touch Up Inside» в контроллер первого представления, выберите метод writeWeightButtonPressed: из всплывающего меню.

Теперь нам нужно подключить розетки, которые мы объявили, к элементам пользовательского интерфейса. Нажмите Control и перетащите из First View Controller на метку с двумя вопросительными знаками. ageLabel всплывающем меню « Outlets» нажмите на ageLabel . Это соединит розетку с этикеткой.

Пользовательский интерфейс - подключение розеток 2

Повторите эти шаги для текстового поля, подключив его к выходу weightTextField контроллера представления.

Пользовательский интерфейс - подключение розеток 3

Первая сцена теперь должна быть полностью функциональной. Запустите приложение и включите переключатель. Вам будет предложено ввести следующий интерфейс пользователя HealthKit:

Интерфейс Health Access

Обязательно включите оба переключателя, прежде чем нажимать « Готово» , иначе у вашего приложения не будет доступа к данным, которые нам нужны в примере приложения.

Теперь вы можете попробовать нажать кнопку « Читать» . Если вы запускаете приложение в iOS Simulator, вероятно, ничего не произойдет, потому что вы не установили дату рождения. Вы можете перейти к приложению Health в iOS Simulator и установить его.

  • Откройте приложение Здоровье.
  • Выберите вкладку Health Data .
  • Коснитесь меня .
  • Нажмите « Изменить» .
  • Нажмите Дата рождения и установите дату. Нажмите Готово .

Теперь вы можете вернуться в наше приложение HealthBasics и снова нажать кнопку « Читать» . На этот раз ваш возраст должен быть отображен.

Вы также можете проверить распределение веса. Выберите текстовое поле веса и введите значение в килограммах. После того как вы нажмете « Написать» , вернитесь в приложение «Здоровье» и на вкладке « Данные о здоровье » выберите « Измерения тела и вес» . Образец, который вы только что добавили, должен быть виден.

HealthKit Вес образца

До сих пор вы изучили основы работы с HealthKit.

  • как запросить у пользователя разрешение
  • как читать и писать основные данные
  • как инкапсулировать связанный с HealthKit код в отдельном классе

Во второй части нашего примера приложения я покажу вам, как написать тренировку в HealthKit. Это полезно, если вы создаете приложение для тренировок (бег, езда на велосипеде, ходьба и т. Д.). Большинство строительных блоков похожи.

Начнем с расширения класса GSHealthKitManager . Добавьте следующее объявление метода в GSHealthKitManager.h :

1
— (void)writeWorkoutDataFromModelObject:(id)workoutModelObject;

Добавьте новый тип requestAuthorizationToShareTypes:readTypes:completion: в requestAuthorizationToShareTypes:readTypes:completion: метод, добавив тип тренировки в массив writeTypes .

1
2
NSArray *writeTypes = @[[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass],
                       [HKObjectType workoutType]];

Наконец, добавьте writeWorkoutDataFromModelObject: метод внизу класса GSHealthKitManager .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
— (void)writeWorkoutDataFromModelObject:(id)workoutModelObject {
     
    // In a real world app, you would pass in a model object representing your workout data, and you would pull the relevant data here and pass it to the HealthKit workout method.
     
    // For the sake of simplicity of this example, we will just set arbitrary data.
    NSDate *startDate = [NSDate date];
    NSDate *endDate = [startDate dateByAddingTimeInterval:60 * 60 * 2];
    NSTimeInterval duration = [endDate timeIntervalSinceDate:startDate];
    CGFloat distanceInMeters = 57000.;
     
    HKQuantity *distanceQuantity = [HKQuantity quantityWithUnit:[HKUnit meterUnit] doubleValue:(double)distanceInMeters];
     
    HKWorkout *workout = [HKWorkout workoutWithActivityType:HKWorkoutActivityTypeRunning
                                                  startDate:startDate
                                                    endDate:endDate
                                                   duration:duration
                                          totalEnergyBurned:nil
                                              totalDistance:distanceQuantity
                                                   metadata:nil];
     
    [self.healthStore saveObject:workout withCompletion:^(BOOL success, NSError *error) {
        NSLog(@»Saving workout to healthStore — success: %@», success ? @»YES» : @»NO»);
        if (error != nil) {
            NSLog(@»error: %@», error);
        }
    }];
}

В моем собственном приложении Routie я использовал подход, заключающийся в передаче объекта модели в метод writeWorkoutDataFromModelObject: делегирование тяжелой работы классу менеджера. Последний извлекает необходимые данные из объекта модели и передает информацию в экземпляр HKHealthStore . Я считаю, что это хороший способ сохранить код, связанный с HealthKit, ограниченным классом менеджера.

Реализация метода writeWorkoutDataFromModelObject: довольно проста. Всего три шага:

  1. Сначала мы подготовим данные. В этом примере мы составляем цифры.
  2. Затем мы создаем объект HKWorkout , вызывая один из удобных инициализаторов класса.
  3. Наконец, мы сохраняем объект HKHealthStore экземпляре HKHealthStore .

Это первый раз, когда мы работаем с классом HKWorkout, поэтому позвольте мне кратко представить этот класс. Платформа HealthKit использует класс HKWorkout для отслеживания действий. Тренировки в основном неизменяемы, поэтому вы должны указать значения тренировки во время инициализации.

При инициализации тренировки вам необходимо указать тип занятия, дату начала и дату окончания. При желании вы можете передать общее расстояние, общую сожженную энергию и метаданные. Метаданные могут быть использованы для назначения дополнительной информации для тренировки. Это действительно полезно, когда вы хотите поделиться дополнительной информацией о тренировке с другим приложением, которое вы также создали.

Откройте SecondViewController.m и добавьте следующий импорт в начало файла:

1
#import «GSHealthKitManager.h»

Затем writeWorkoutButtonPressed: метод writeWorkoutButtonPressed: как показано ниже.

1
2
3
4
5
— (IBAction)writeWorkoutButtonPressed:(id)sender {
    // In a real world app, you would obtain reference to a relevant model object and pass it to following method.
    [[GSHealthKitManager sharedManager] requestAuthorization];
    [[GSHealthKitManager sharedManager] writeWorkoutDataFromModelObject:nil];
}

Мы просто добавим одну кнопку во вторую сцену приложения, чтобы написать тренировку. Откройте Main.storyboard и сфокусируйтесь на второй сцене. Удалите метки, которые в данный момент находятся во втором контроллере вида.

Добавьте кнопку в центре представления контроллера представления и установите для ее заголовка « Запись тренировки» . Соедините его событие Touch Up Inside с writeWorkoutButtonPressed: действие, которое мы реализовали на предыдущем шаге.

Создайте и запустите приложение и включите переключатель интеграции работоспособности. Экран « Доступ к работоспособности» будет представлен с отключенным новым запрошенным типом тренировки. Включите его и нажмите Готово . Это необходимо только потому, что мы добавили тип общего ресурса тренировки в список типов общих ресурсов. Это означает, что мы должны запросить у пользователя разрешение, прежде чем его использовать.

HealthKit Health Access UI

Откройте вторую вкладку внизу и нажмите « Запись тренировки» . Если все прошло правильно, вы должны увидеть следующее сообщение в консоли Xcode:

1
Saving workout to healthStore — success: YES

Теперь вы можете переключиться в приложение «Здоровье» и перейти в « Данные о здоровье» > « Фитнес» > « Тренировки» . Там вы должны увидеть только что добавленную тренировку.

HealthKit - Пример тренировки

В этом уроке я показал вам, как вы можете написать тренировку в HealthKit. Я также показал вам, как отделить код, связанный с HealthKit, передав объект модели в метод, который записывает тренировку в HealthKit.

Я надеюсь, что вам понравился этот урок, и вы изучили все основы, необходимые для того, чтобы выйти и интегрировать свое собственное приложение с HealthKit. Я также надеюсь, что убедил вас попробовать HealthKit.

Дайте мне знать в комментариях, как вам понравился этот урок или если что-то было неясно. Вы также можете найти меня в Twitter .

Приведенный ниже список содержит ряд релевантных ссылок, поэтому вы можете быстро перейти к тому, что вам нужно: