HealthKit в Xamarin.iOS

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

Так как данные, связанные с здоровьем, настолько чувствительны и важны, набор работоспособности строго типизирован, с единицами измерения и явной связью с типом информации, записанной (например, уровень глюкозы в крови или частоту пульса). Кроме того, приложения набора работоспособности должны использовать явные права, должны запрашивать доступ к определенным типам информации, а пользователь должен явно предоставить приложению доступ к этим типам данных.

В этой статье описано:

  • Требования к безопасности комплекта работоспособности, включая подготовку приложений и запрос разрешения пользователя на доступ к базе данных набора работоспособности;
  • Система типов набора работоспособности, которая сводит к минимуму возможность неправильного применения или неправильного толкования данных;
  • Запись в общее хранилище данных комплекта работоспособности на всей системе.

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

В этой статье мы создадим пример приложения для записи частоты пульса пользователя:

A sample application to record the users heart rate

Требования

Для выполнения описанных в этой статье действий необходимо выполнить следующие действия.

  • Xcode 7 и iOS 8 (или более поздней версии) — последние API Xcode и iOS Apple должны быть установлены и настроены на компьютере разработчика.
  • Visual Studio для Mac или Visual Studio — последняя версия Visual Studio для Mac должна быть установлена и настроена на компьютере разработчика.
  • Устройство iOS 8 (или более поздней версии) — устройство iOS с последней версией iOS 8 или более поздней для тестирования.

Внимание

Набор работоспособности появился в iOS 8. В настоящее время набор работоспособности недоступен в симуляторе iOS, а отладка требует подключения к физическому устройству iOS.

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

Прежде чем приложение Xamarin iOS 8 может использовать API HealthKit, оно должно быть правильно настроено и подготовлено. В этом разделе описаны действия, необходимые для правильной настройки приложения Xamarin.

Для приложений комплекта работоспособности требуется:

  • Явный идентификатор приложения.
  • Профиль подготовки, связанный с этим явным идентификатором приложения и разрешениями комплекта работоспособности.
  • Свойство Entitlements.plist типа Boolean с заданным com.apple.developer.healthkit значением Yes.
  • КлючInfo.plist, ключ которого UIRequiredDeviceCapabilities содержит запись со значениемhealthkitString.
  • Также Info.plist должны быть соответствующие записи о конфиденциальности: String объяснение ключа, если приложение собирается записывать данные и String объяснение ключа NSHealthUpdateUsageDescriptionNSHealthShareUsageDescription, если приложение собирается считывать данные набора работоспособности.

Чтобы узнать больше о подготовке приложения iOS, в статье "Подготовка устройств" в серии "Начало работы" Xamarin описывается связь между сертификатами разработчиков, идентификаторами приложений, профилями подготовки и правами приложений.

Явный идентификатор приложения и профиль подготовки

Создание явного идентификатора приложения и соответствующего профиля подготовки выполняется в Центр разработки Apple iOS.

Текущие идентификаторы приложений перечислены в разделе "Сертификаты, идентификаторы и профили" Центр разработки. Часто в этом списке отображаются значения идентификаторов*, указывающие, что имя идентификатора - приложения можно использовать с любым числом суффиксов. Такие дикие карта идентификаторы приложений нельзя использовать с набором работоспособности.

Чтобы создать явный идентификатор приложения, нажмите + кнопку в правом верхнем углу, чтобы перейти на страницу "Регистрация идентификатора приложения iOS":

Registering an app on the Apple Developer Portal

Как показано на рисунке выше, после создания описания приложения используйте раздел "Явный идентификатор приложения" для создания идентификатора приложения. В разделе Служба приложений проверка набор работоспособности в разделе "Включить службы".

По завершении нажмите кнопку "Продолжить ", чтобы зарегистрировать идентификатор приложения в учетной записи. Вы вернеесь на страницу "Сертификаты", "Идентификаторы" и "Профили ". Нажмите кнопку "Профили подготовки" , чтобы перейти к списку текущих профилей подготовки, и нажмите + кнопку в правом верхнем углу, чтобы перейти на страницу "Добавить профиль подготовки iOS". Выберите параметр разработки приложений iOS и нажмите кнопку "Продолжить", чтобы перейти на страницу "Выбор идентификатора приложения". Здесь выберите явный идентификатор приложения, указанный ранее:

Select the explicit App ID

Нажмите кнопку "Продолжить" и пройдите остальные экраны, где вы укажете сертификаты разработчика, устройства и имя этого профиля подготовки:

Generating the Provisioning Profile

Нажмите кнопку "Создать" и ожидайте создания профиля. Скачайте файл и дважды щелкните его, чтобы установить в Xcode. Вы можете подтвердить установку в разделе "Учетные записи > параметров > Xcode>", чтобы просмотреть сведения... Вы должны увидеть только что установленный профиль подготовки, и он должен иметь значок для комплекта работоспособности и любых других специальных служб в строке "Права".

Viewing the profile in Xcode

Связывание идентификатора приложения и профиля подготовки с приложением Xamarin.iOS

После создания и установки соответствующего профиля подготовки, как описано, обычно будет время создать решение в Visual Studio для Mac или Visual Studio. Доступ к комплекту работоспособности доступен для любого проекта C# или F# iOS.

Вместо того чтобы пройти процесс создания проекта Xamarin iOS 8 вручную, откройте пример приложения, присоединенного к этой статье (который включает предварительно созданную раскадровки и код). Чтобы связать пример приложения с включенным профилем подготовки набора работоспособности, на панели решений щелкните правой кнопкой мыши проект и откройте диалоговое окно "Параметры". Перейдите на панель приложений iOS и введите явный идентификатор приложения, созданный ранее в качестве идентификатора пакета приложения:

Enter the explicit App ID

Теперь перейдите на панель подписывания пакета iOS. Недавно установленный профиль подготовки с явным идентификатором приложения теперь будет доступен в качестве профиля подготовки:

Select the Provisioning Profile

Если профиль подготовки недоступен, дважды проверка идентификатор пакета на панели приложений iOS и то, что указано в Центр разработки iOS, и что профиль подготовки установлен (сведения об просмотре учетных > записей параметров > Xcode>...).

Если выбран профиль подготовки с поддержкой набора работоспособности, нажмите кнопку "ОК", чтобы закрыть диалоговое окно "Параметры проекта".

Значения entitlements.plist и Info.plist

Пример приложения содержит файл (который необходим для приложений с включенным набором Entitlements.plist работоспособности) и не включается в каждый шаблон проекта. Если проект не содержит прав, щелкните правой кнопкой мыши проект, выберите файл > нового файла... > iOS > Entitlements.plist , чтобы добавить его вручную.

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

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.HealthKit</key>
    <true/>
</dict>
</plist>

Аналогичным образом приложение Info.plist должно иметь значение healthkit , связанное с ключом UIRequiredDeviceCapabilities :

<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
    <string>healthkit</string>
</array>

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

Набор работоспособности программирования

Хранилище данных Набора работоспособности — это частное хранилище данных, которое предоставляется пользователям. Так как сведения о работоспособности настолько конфиденциальны, пользователь должен принять положительные меры, чтобы разрешить доступ к данным. Этот доступ может быть частичным (запись, но не чтение, доступ для некоторых типов данных, но не других и т. д.) и может быть отменен в любое время. Приложения комплекта работоспособности должны быть написаны оборонительно, с пониманием того, что многие пользователи будут невнимательно хранить информацию, связанную со здоровьем.

Данные комплекта работоспособности ограничены указанными типами Apple. Эти типы строго определены: некоторые, такие как тип крови, ограничены определенными значениями предоставленного перечисления Apple, а другие объединяют величину с единицей измерения (например, граммы, калорий и литров). Даже данные, которые совместно используют совместимую единицу измерения, отличаются их HKObjectType; например, система типов перехватит ошибку попытки сохранить HKQuantityTypeIdentifier.NumberOfTimesFallen значение в поле, ожидающее HKQuantityTypeIdentifier.FlightsClimbed , хотя оба используют HKUnit.Count единицу измерения.

Типы, храняемые в хранилище данных Набора работоспособности, являются подклассами HKObjectType. HKCharacteristicType объекты хранят биологический секс, тип крови и дату рождения. Более распространенными, однако, являются HKSampleType объекты, представляющие данные, образцы которых выполняются в определенное время или в течение определенного периода времени.

HKSampleType objects chart

HKSampleType является абстрактным и имеет четыре конкретных подкласса. В настоящее время существует только один тип HKCategoryType данных, который является анализом сна. Большинство данных в наборе работоспособности имеют тип HKQuantityType и хранят свои данные в HKQuantitySample объектах, которые создаются с помощью знакомого шаблона конструктора фабрики:

The large majority of data in Health Kit are of type HKQuantityType and store their data in HKQuantitySample objects

HKQuantityType Диапазон типов от HKQuantityTypeIdentifier.ActiveEnergyBurned до HKQuantityTypeIdentifier.StepCount.

Запрос разрешения от пользователя

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

The user is presented with a system-controlled Health Access dialog

Позже пользователь может изменить разрешения с помощью диалогового окна "Источники " приложения работоспособности:

The user can change permissions using Health apps Sources dialog

Так как сведения о работоспособности очень чувствительны, разработчики приложений должны писать свои программы оборонительным образом, с ожиданием того, что разрешения будут отклонены и изменены во время работы приложения. Наиболее распространенная идиома — запрашивать разрешения в методе UIApplicationDelegate.OnActivated , а затем изменять пользовательский интерфейс соответствующим образом.

Пошаговое руководство по разрешениям

В подготовленном пакете работоспособности откройте AppDelegate.cs файл. Обратите внимание на инструкцию using HealthKit; в верхней части файла.

Следующий код относится к разрешениям набора работоспособности:

private HKHealthStore healthKitStore = new HKHealthStore ();

public override void OnActivated (UIApplication application)
{
        base.OnActivated(application);
        ValidateAuthorization ();
}

private void ValidateAuthorization ()
{
        var heartRateId = HKQuantityTypeIdentifierKey.HeartRate;
        var heartRateType = HKObjectType.GetQuantityType (heartRateId);
        var typesToWrite = new NSSet (new [] { heartRateType });
        var typesToRead = new NSSet ();
        healthKitStore.RequestAuthorizationToShare (
                typesToWrite, 
                typesToRead, 
                ReactToHealthCarePermissions);
}

void ReactToHealthCarePermissions (bool success, NSError error)
{
        var access = healthKitStore.GetAuthorizationStatus (HKObjectType.GetQuantityType (HKQuantityTypeIdentifierKey.HeartRate));
        if (access.HasFlag (HKAuthorizationStatus.SharingAuthorized)) {
                HeartRateModel.Instance.Enabled = true;
        } else {
                HeartRateModel.Instance.Enabled = false;
        }
}

Весь код в этих методах можно сделать встроенным OnActivated, но в примере приложения используются отдельные методы, чтобы сделать его намерение более понятным: ValidateAuthorization() имеет шаги, необходимые для запроса доступа к определенным типам, написанным (и чтение, если приложение нужно) и ReactToHealthCarePermissions() является обратным вызовом, который активируется после того, как пользователь взаимодействовал с диалогом разрешений в Health.app.

Задание ValidateAuthorization() состоит в том, чтобы создать набор HKObjectTypes , который приложение будет записывать и запрашивать авторизацию для обновления этих данных. В примере приложения HKObjectType используется ключ KHQuantityTypeIdentifierKey.HeartRate. Этот тип добавляется в набор typesToWrite, а набор typesToRead остается пустым. Эти наборы и ссылка на обратный ReactToHealthCarePermissions() вызов передаются HKHealthStore.RequestAuthorizationToShare()в .

Обратный ReactToHealthCarePermissions() вызов будет вызываться после взаимодействия пользователя с диалоговым окном разрешений и передается две части информации: bool значение, которое будет иметь значение true , если пользователь взаимодействовал с диалогом разрешений и NSError каким, если он не имеет значения NULL, указывает на некоторую ошибку, связанную с представлением диалогового окна разрешений.

Внимание

Чтобы узнать о аргументах этой функции, параметры успешности и ошибки не указывают, предоставил ли пользователь разрешение на доступ к данным набора работоспособности! Они указывают, что пользователю предоставлена возможность разрешить доступ к данным.

Чтобы подтвердить, имеет ли приложение доступ к данным, HKHealthStore.GetAuthorizationStatus() используется, передавая HKQuantityTypeIdentifierKey.HeartRateего. В зависимости от возвращенного состояния приложение включает или отключает возможность ввода данных. Нет стандартного интерфейса пользователя для работы с отказом в доступе, и существует множество возможных вариантов. В примере приложения состояние устанавливается в HeartRateModel одном объекте, который, в свою очередь, вызывает соответствующие события.

Модель, представление и контроллер

Чтобы просмотреть HeartRateModel одноэлементный HeartRateModel.cs объект, откройте файл:

using System;
using HealthKit;
using Foundation;

namespace HKWork
{
        public class GenericEventArgs<T> : EventArgs
        {
                public T Value { get; protected set; }
                public DateTime Time { get; protected set; }

                public GenericEventArgs (T value)
                {
                        this.Value = value;
                        Time = DateTime.Now;
                }
        }

        public delegate void GenericEventHandler<T> (object sender,GenericEventArgs<T> args);

        public sealed class HeartRateModel : NSObject
        {
                private static volatile HeartRateModel singleton;
                private static object syncRoot = new Object ();

                private HeartRateModel ()
                {
                }

                public static HeartRateModel Instance {
                        get {
                                //Double-check lazy initialization
                                if (singleton == null) {
                                        lock (syncRoot) {
                                                if (singleton == null) {
                                                        singleton = new HeartRateModel ();
                                                }
                                        }
                                }

                                return singleton;
                        }
                }

                private bool enabled = false;

                public event GenericEventHandler<bool> EnabledChanged;
                public event GenericEventHandler<String> ErrorMessageChanged;
                public event GenericEventHandler<Double> HeartRateStored;

                public bool Enabled { 
                        get { return enabled; }
                        set {
                                if (enabled != value) {
                                        enabled = value;
                                        InvokeOnMainThread(() => EnabledChanged (this, new GenericEventArgs<bool>(value)));
                                }
                        }
                }

                public void PermissionsError(string msg)
                {
                        Enabled = false;
                        InvokeOnMainThread(() => ErrorMessageChanged (this, new GenericEventArgs<string>(msg)));
                }

                //Converts its argument into a strongly-typed quantity representing the value in beats-per-minute
                public HKQuantity HeartRateInBeatsPerMinute(ushort beatsPerMinute)
                {
                        var heartRateUnitType = HKUnit.Count.UnitDividedBy (HKUnit.Minute);
                        var quantity = HKQuantity.FromQuantity (heartRateUnitType, beatsPerMinute);

                        return quantity;
                }
                        
                public void StoreHeartRate(HKQuantity quantity)
                {
                        var bpm = HKUnit.Count.UnitDividedBy (HKUnit.Minute);
                        //Confirm that the value passed in is of a valid type (can be converted to beats-per-minute)
                        if (! quantity.IsCompatible(bpm))
                        {
                                InvokeOnMainThread(() => ErrorMessageChanged(this, new GenericEventArgs<string> ("Units must be compatible with BPM")));
                        }

                        var heartRateId = HKQuantityTypeIdentifierKey.HeartRate;
                        var heartRateQuantityType = HKQuantityType.GetQuantityType (heartRateId);
                        var heartRateSample = HKQuantitySample.FromType (heartRateQuantityType, quantity, new NSDate (), new NSDate (), new HKMetadata());

                        using (var healthKitStore = new HKHealthStore ()) {
                                healthKitStore.SaveObject (heartRateSample, (success, error) => {
                                        InvokeOnMainThread (() => {
                                                if (success) {
                                                        HeartRateStored(this, new GenericEventArgs<Double>(quantity.GetDoubleValue(bpm)));
                                                } else {
                                                        ErrorMessageChanged(this, new GenericEventArgs<string>("Save failed"));
                                                }
                                                if (error != null) {
                                                        //If there's some kind of error, disable 
                                                        Enabled = false;
                                                        ErrorMessageChanged (this, new GenericEventArgs<string>(error.ToString()));
                                                }
                                        });
                                });
                        }
                }
        }
}

Первый раздел — это стандартный код для создания универсальных событий и обработчиков. Начальная часть класса также является стандартной для создания потока безопасного HeartRateModel одноэлементного объекта.

HeartRateModel Затем предоставляет 3 события:

  • EnabledChanged — указывает, что хранилище частоты пульса было включено или отключено (обратите внимание, что хранилище изначально отключено).
  • ErrorMessageChanged — Для этого примера приложения у нас есть очень простая модель обработки ошибок: строка с последней ошибкой.
  • HeartRateStored — возникает при хранении частоты пульса в базе данных комплекта работоспособности.

Обратите внимание, что каждый раз, когда эти события будут запущены, оно выполняется с помощью NSObject.InvokeOnMainThread(), что позволяет подписчикам обновлять пользовательский интерфейс. Кроме того, события можно задокументировать как создаваемые в фоновых потоках, а также ответственность за обеспечение совместимости может быть оставлена обработчикам. Рекомендации по потоку важны в приложениях комплекта работоспособности, так как многие функции, такие как запрос разрешений, являются асинхронными и выполняют обратные вызовы для не основных потоков.

Определенный код HeartRateModel хит-комплекта находится в двух функциях HeartRateInBeatsPerMinute() и StoreHeartRate().

HeartRateInBeatsPerMinute() преобразует его аргумент в строго типизированный набор HKQuantityработоспособности. Тип количества заключается в том, что заданные HKQuantityTypeIdentifierKey.HeartRate единицами количества делятся HKUnit.Count на HKUnit.Minute (иными словами, единица ударов в минуту).

Функция StoreHeartRate() принимает HKQuantity (в примере приложения, созданного с помощью HeartRateInBeatsPerMinute() ). Для проверки данных он использует HKQuantity.IsCompatible() метод, который возвращает true , если единицы объекта можно преобразовать в единицы в аргументе. Если количество было создано с HeartRateInBeatsPerMinute() этим, trueочевидно, возвращается, но он также возвращается true , если количество было создано как, например, Beats в час. HKQuantity.IsCompatible() Чаще всего можно использовать для проверки массы, расстояния и энергии, которые пользователь или устройство могут вводить или отображать в одной системе измерения (например, в имперских единицах), но которые могут храниться в другой системе (например, единицы метрик).

После проверки HKQuantitySample.FromType() совместимости количества используется метод фабрики для создания строго типизированного heartRateSample объекта. HKSample объекты имеют дату начала и окончания; для мгновенного чтения эти значения должны совпадать, как в примере. Пример также не задает данные значения ключа в его HKMetadata аргументе, но можно использовать код, например следующий код, чтобы указать расположение датчика:

var hkm = new HKMetadata();
hkm.HeartRateSensorLocation = HKHeartRateSensorLocation.Chest;

heartRateSample После создания код создает новое подключение к базе данных с помощью блока using. В этом блоке HKHealthStore.SaveObject() метод пытается асинхронную запись в базу данных. Результирующий вызов лямбда-выражения активирует соответствующие события либо HeartRateStoredErrorMessageChanged.

Теперь, когда модель была запрограммирована, пришло время узнать, как контроллер отражает состояние модели. Откройте файл HKWorkViewController.cs. Конструктор просто преобразует HeartRateModel одинтон в методы обработки событий (опять же, это можно сделать в виде лямбда-выражений, но отдельные методы делают намерение немного более очевидным):

public HKWorkViewController (IntPtr handle) : base (handle)
{
     HeartRateModel.Instance.EnabledChanged += OnEnabledChanged;
     HeartRateModel.Instance.ErrorMessageChanged += OnErrorMessageChanged;
     HeartRateModel.Instance.HeartRateStored += OnHeartBeatStored;
}

Ниже приведены соответствующие обработчики:

void OnEnabledChanged (object sender, GenericEventArgs<bool> args)
{
        StoreData.Enabled = args.Value;
        PermissionsLabel.Text = args.Value ? "Ready to record" : "Not authorized to store data.";
        PermissionsLabel.SizeToFit ();
}

void OnErrorMessageChanged (object sender, GenericEventArgs<string> args)
{
        PermissionsLabel.Text = args.Value;
}

void OnHeartBeatStored (object sender, GenericEventArgs<double> args)
{
        PermissionsLabel.Text = String.Format ("Stored {0} BPM", args.Value);
}

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

Запуск примера приложения

Симулятор iOS не поддерживает набор работоспособности. Отладка должна выполняться на физическом устройстве под управлением iOS 8.

Подключите правильно подготовленное устройство разработки iOS 8 к вашей системе. Выберите его в качестве целевого объекта развертывания в Visual Studio для Mac и в меню выберите команду "Выполнить > отладку".

Внимание

Ошибки, связанные с подготовкой, будут отображаться на этом этапе. Чтобы устранить ошибки, ознакомьтесь с приведенным выше разделом "Создание и подготовка приложения комплекта работоспособности". Компоненты:

  • IOS Центр разработки — явный идентификатор приложения и комплект работоспособности с включенным профилем подготовки.
  • Параметры проекта — идентификатор пакета (явный идентификатор приложения) и профиль подготовки.
  • Исходный код — Entitlements.plist и Info.plist

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

The user will be presented with this dialog

Включите приложение для обновления данных о частоте сердечных сокращений, и ваше приложение будет повторно появляться. Обратный ReactToHealthCarePermissions вызов будет активирован асинхронно. HeartRateModel’sEnabled Это приведет к изменению свойства, EnabledChanged которое приведет к возникновению события, что приведет HKPermissionsViewController.OnEnabledChanged() к выполнению обработчика событий, который включает кнопкуStoreData. На следующей схеме показана последовательность:

This diagram shows the sequence of events

Нажмите кнопку "Запись ". Это приведет StoreData_TouchUpInside() к выполнению обработчика, который попытается проанализировать значение текстового heartRate поля, преобразовать в функцию HKQuantity , описанную HeartRateModel.HeartRateInBeatsPerMinute() ранее, и передать это количество HeartRateModel.StoreHeartRate(). Как уже говорилось ранее, это попытается сохранить данные и вызовет событие HeartRateStored или ErrorMessageChanged событие.

Дважды щелкните кнопку "Главная" на устройстве и откройте приложение "Работоспособность". Щелкните вкладку "Источники" , и вы увидите пример приложения. Выберите его и запретите разрешение на обновление данных частоты пульса. Дважды щелкните кнопку "Главная" и вернитесь в приложение. Еще раз вызовется, ReactToHealthCarePermissions() но на этот раз, так как доступ запрещен, кнопка StoreData будет отключена (обратите внимание, что это происходит асинхронно, и изменение в пользовательском интерфейсе может отображаться для конечного пользователя).

Дополнительные разделы

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

Существует ряд более сложных функций запросов, позволяющих выполнять запросы и запросы на основе предиката, которые выполняют обновления при обновлении соответствующих данных.

Разработчики приложений комплекта работоспособности должны ознакомиться с разделом "Комплект работоспособности" в руководстве по проверке приложений Apple.

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

По состоянию на написание этой статьи в настоящее время нет эквивалента комплекту работоспособности в Android или Windows Телефон.

Итоги

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

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

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