HealthKit en Xamarin.iOS

El Kit de mantenimiento proporciona un almacén de datos seguro para la información relacionada con el estado del usuario. Las aplicaciones del Kit de mantenimiento pueden, con el permiso explícito del usuario, leer y escribir en este almacén de datos y recibir notificaciones cuando se agregan datos pertinentes. Las aplicaciones pueden presentar los datos o los usuarios pueden usar la aplicación Health proporcionada por Apple para ver un panel de todos sus datos.

Dado que los datos relacionados con la salud son tan sensibles y cruciales, Health Kit está fuertemente tipado, con unidades de medida y una asociación explícita con el tipo de información que se registra (por ejemplo, nivel de glucosa en sangre o frecuencia cardíaca). Además, las aplicaciones Health Kit deben usar derechos explícitos, deben solicitar acceso a los tipos concretos de información y el usuario debe conceder explícitamente al usuario acceso a esos tipos de datos.

En este artículo se presenta lo siguiente:

  • Los requisitos de seguridad de Health Kit, incluido el aprovisionamiento de aplicaciones y la solicitud de permiso de usuario para acceder a la base de datos de Health Kit;
  • El sistema de tipos de Health Kit, que minimiza la posibilidad de aplicar o interpretar datos incorrectamente;
  • La escritura en el almacén de datos compartido de Health Kit para todo el sistema.

En este artículo no se tratarán temas más avanzados, como consultar la base de datos, convertir entre unidades de medida o recibir notificaciones de nuevos datos.

En este artículo, vamos a crear una aplicación de ejemplo para registrar la frecuencia cardíaca del usuario:

Una aplicación de ejemplo para registrar la frecuencia cardíaca de los usuarios

Requisitos

Se requiere lo siguiente para completar los pasos presentados en este artículo:

  • Xcode 7 e iOS 8 (o posterior): las API de Xcode e iOS más recientes de Apple deben instalarse y configurarse en el equipo del desarrollador.
  • Visual Studio para Mac o Visual Studio: la versión más reciente de Visual Studio para Mac debe instalarse y configurarse en el equipo del desarrollador.
  • Dispositivo iOS 8 (o superior): un dispositivo iOS que ejecuta la versión más reciente de iOS 8 o posterior para las pruebas.

Importante

Health Kit se incluyó por primera vez en iOS 8. Actualmente, Health Kit no está disponible en el simulador de iOS y la depuración requiere conexión a un dispositivo iOS físico.

Creación y aprovisionamiento de una aplicación de Health Kit

Antes de que una aplicación de Xamarin iOS 8 pueda usar la API de HealthKit, debe configurarse y aprovisionarse correctamente. En esta sección se tratarán los pasos necesarios para configurar correctamente la aplicación de Xamarin.

Las aplicaciones Health Kit requieren:

  • Un identificador de aplicación explícito.
  • Un perfil de aprovisionamiento asociado a ese identificador de aplicación explícito y con permisos de Health Kit.
  • Un Entitlements.plist con una propiedad com.apple.developer.healthkit de tipo Boolean establecida en Yes.
  • Un Info.plist cuya clave UIRequiredDeviceCapabilities contiene una entrada con el valor String en healthkit.
  • Info.plist también debe tener entradas apropiadas de explicación de privacidad: una explicación String para la clave NSHealthUpdateUsageDescription si la aplicación va a escribir datos y una explicación String para la clave NSHealthShareUsageDescription si la aplicación va a leer datos de Health Kit.

Para obtener más información sobre el aprovisionamiento de una aplicación de iOS, en el artículo Aprovisionamiento de dispositivos de la serie Introducción de Xamarin se describe la relación entre los certificados de desarrollador, los identificadores de aplicación, los perfiles de aprovisionamiento y los derechos de aplicación.

Identificador de aplicación explícito y perfil de aprovisionamiento

La creación de un identificador de aplicación explícito y un perfil de aprovisionamiento adecuado se realiza en el Centro de desarrollo de iOS de Apple.

Sus identificadores de aplicación actuales se encuentran en la sección Certificados, identificadores y perfiles del Centro de desarrollo. A menudo, esta lista mostrará los valores ID de *, lo que indica que Identificador de aplicación - Nombre puede utilizarse con cualquier número de sufijos. Estos identificadores de aplicación comodín no se pueden usar con Health Kit.

Para crear un identificador de aplicación explícito, haga clic en el botón + situado en la parte superior derecha para acceder a la página Registrar identificador de aplicación de iOS:

Registrar una aplicación en el Portal para desarrolladores de Apple

Como se muestra en la imagen anterior, después de crear una descripción de la aplicación, utilice la sección Identificador de aplicación explícito para crear un identificador para su aplicación. En la sección App Services, active Health Kit en la sección Habilitar servicios.

Cuando haya terminado, presione el botón Continuar para registrar el identificador de aplicación en su cuenta. Volverá a la página Certificados, identificadores y perfiles. Haga clic en Perfiles de aprovisionamiento para acceder a la lista de sus perfiles de aprovisionamiento actuales y haga clic en el botón + situado en la esquina superior derecha para acceder a la página Agregar perfil de aprovisionamiento de iOS. Seleccione la opción Desarrollo de aplicaciones iOS y haga clic en Continuar para acceder a la página Seleccionar identificador de aplicación. Aquí, seleccione el identificador de aplicación explícito que especificó anteriormente:

Seleccionar el identificador de aplicación explícito

Haga clic en Continuar y trabaje con las pantallas restantes, donde especificará los certificados de desarrollador, los dispositivos y un nombre para este perfil de aprovisionamiento:

Generar el perfil de aprovisionamiento

Haga clic en Generar y espere a la creación del perfil. Descargue el archivo y haga doble clic en él para instalarlo en Xcode. Puedes confirmar su instalación en Xcode > Preferencias > Cuentas > Ver detalles... Debería ver su perfil de aprovisionamiento recién instalado, y debería tener el icono de Health Kit y cualquier otro servicio especial en su fila Derechos:

Visualización del perfil en Xcode

Asociación del identificador de aplicación y el perfil de aprovisionamiento con la aplicación de Xamarin.iOS

Una vez que haya creado e instalado un perfil de aprovisionamiento adecuado como se describe, normalmente sería el momento de crear una solución en Visual Studio para Mac o Visual Studio. El acceso al Health Kit está disponible para cualquier proyecto de C# o F# de iOS.

En lugar de recorrer el proceso de creación de un proyecto de Xamarin iOS 8 a mano, abra la aplicación de ejemplo adjunta a este artículo (que incluye un guión gráfico y código precompilados). Para asociar la aplicación de ejemplo con su Perfil de aprovisionamiento de Health Kit activado, en el Panel de solución, haga clic con el botón derecho en su proyecto y abra el cuadro de diálogo Opciones. Cambie al panel Aplicación de iOS y escriba el identificador de aplicación explícito que creó anteriormente como identificador de lote de la aplicación:

Escribir el identificador de aplicación explícito

Ahora cambie al panel Firma de lote de iOS. Su perfil de aprovisionamiento recién instalado, con su asociación al identificador de aplicación explícito, estará ahora disponible como Perfil de aprovisionamiento:

Seleccionar el perfil de aprovisionamiento

Si el Perfil de aprovisionamiento no está disponible, compruebe de nuevo el identificador de lote en el panel Aplicación de iOS en comparación con el especificado en el Centro de desarrollo de iOS y que el Perfil de aprovisionamiento está instalado (Xcode > Preferencias > Cuentas > Ver detalles...).

Cuando se seleccione el perfil de aprovisionamiento habilitado para Health Kit, haga clic en Aceptar para cerrar el cuadro de diálogo Opciones del proyecto.

Valores Info.plist y Entitlements.plist

La aplicación de ejemplo incluye un archivo Entitlements.plist (necesario para las aplicaciones habilitadas para Health Kit), que no se incluye en todas las plantillas de proyecto. Si su proyecto no incluye derechos, haga clic con el botón derecho en su proyecto, seleccione Archivo >Nuevo archivo... > iOS > Entitlements.plist para agregar uno manualmente.

En última instancia, su Entitlements.plist debe tener el siguiente par clave y valor:

<?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>

Del mismo modo, el Info.plist de la aplicación debe tener un valor de healthkit asociado a la clave UIRequiredDeviceCapabilities:

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

La aplicación de ejemplo proporcionada con este artículo incluye un Entitlements.plist preconfigurado que incluye todas las claves necesarias.

Programación de Health Kit

El almacén de datos de Health Kit es un almacén de datos privado específico del usuario que se comparte entre aplicaciones. Dado que la información sanitaria es tan confidencial, el usuario debe tomar medidas positivas para permitir el acceso a los datos. Este acceso puede ser parcial (escritura, pero no lectura, acceso para algunos tipos de datos, pero no otros, etc.) y se puede revocar en cualquier momento. Las aplicaciones de Health Kit deben escribirse a la defensiva, entendiendo que muchos usuarios dudarán a la hora de almacenar información relacionada con su salud.

Los datos de Health Kit se limitan a los tipos especificados de Apple. Estos tipos se definen estrictamente: algunos, como el tipo de sangre, están limitados a los valores concretos de una enumeración suministrada por Apple, mientras que otros combinan una magnitud con una unidad de medida (como gramos, calorías y litros). Incluso los datos que comparten una unidad de medida compatible se distinguen por su HKObjectType; por ejemplo, el sistema de tipos detectará un intento erróneo de almacenar un HKQuantityTypeIdentifier.NumberOfTimesFallen en un campo que espera un HKQuantityTypeIdentifier.FlightsClimbed aunque ambos usen la unidad de medida HKUnit.Count.

Los tipos que se pueden almacenar en el almacén de datos de Health Kit son todas las subclases de HKObjectType. Los objetos HKCharacteristicType almacenan el sexo biológico, el tipo de sangre y la fecha de nacimiento. Sin embargo, más comunes son los objetos HKSampleType, que representan los datos que se muestrean en un momento específico o durante un período de tiempo.

Gráfico de objetos HKSampleType

HKSampleType es abstracto y tiene cuatro subclases concretas. Actualmente sólo hay un tipo de datos HKCategoryType, que es el análisis del sueño. La mayor parte de los datos de Health Kit son de tipo HKQuantityType y almacenan sus datos en objetos HKQuantitySample que se crean mediante el conocido patrón de diseño Factory:

La mayor parte de los datos del Kit de Salud son de tipo HKQuantityType y almacenan sus datos en objetos HKQuantitySample

Los tipos HKQuantityType van de HKQuantityTypeIdentifier.ActiveEnergyBurned a HKQuantityTypeIdentifier.StepCount.

Solicitud de permiso del usuario

Los usuarios finales deben tomar medidas positivas para permitir que una aplicación lea o escriba datos de Health Kit. Esto se hace a través de la aplicación Salud que viene preinstalada en dispositivos iOS 8. La primera vez que se ejecuta una aplicación de Health Kit, se presenta al usuario un cuadro de diálogo Acceso a la salud controlado por el sistema:

El usuario se presenta con un cuadro de diálogo Acceso a Salud controlado por el sistema

Más adelante, el usuario puede cambiar los permisos mediante el cuadro de diálogo Orígenes de la aplicación Salud:

El usuario puede cambiar los permisos mediante el cuadro de diálogo Orígenes de la aplicación Salud

Dado que la información sanitaria es extremadamente confidencial, los desarrolladores de aplicaciones deben escribir sus programas a la defensiva, con la expectativa de que los permisos se denegarán y cambiarán mientras la aplicación esté en funcionamiento. Lo más habitual es solicitar permisos en el método UIApplicationDelegate.OnActivated y luego modificar la interfaz de usuario según convenga.

Tutorial de permisos

En el proyecto aprovisionado por el Health Kit, abra el archivo AppDelegate.cs. Observe la instrucción que usa HealthKit en la parte superior del archivo.

El código siguiente está relacionado con los permisos de Health Kit:

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;
        }
}

Todo el código de estos métodos podría estar en línea en OnActivated, pero la aplicación de ejemplo utiliza métodos separados para que su intención sea más clara: ValidateAuthorization() tiene los pasos necesarios para solicitar el acceso a los tipos específicos que se están escribiendo (y leyendo, si la aplicación lo desea) y ReactToHealthCarePermissions() es una devolución de llamada que se activa después de que el usuario haya interactuado con el diálogo de permisos en Health.app.

El trabajo de ValidateAuthorization() consiste en compilar el conjunto de HKObjectTypes que la aplicación escribirá y solicitar autorización para actualizar esos datos. En la aplicación de ejemplo, HKObjectType es para la clave KHQuantityTypeIdentifierKey.HeartRate. Este tipo se agrega al conjunto typesToWrite, mientras que el conjunto typesToRead se deja vacío. Estos conjuntos y una referencia a la devolución de llamada ReactToHealthCarePermissions() se pasan a HKHealthStore.RequestAuthorizationToShare().

Se llamará a la devolución de llamada ReactToHealthCarePermissions() después de que el usuario haya interactuado con el cuadro de diálogo de permisos y se pasen dos fragmentos de información: un valor bool que será true si el usuario ha interactuado con el cuadro de diálogo de permisos y un NSError que, si no es nulo, indica algún tipo de error asociado con la presentación del cuadro de diálogo de permisos.

Importante

Para aclarar los argumentos de esta función: los parámetros success y error no indican si el usuario ha concedido permiso para acceder a los datos de Health Kit. Solo indican que al usuario se le ha concedido la oportunidad de permitir el acceso a los datos.

Para confirmar si la app tiene acceso a los datos, se utiliza HKHealthStore.GetAuthorizationStatus() y se pasa HKQuantityTypeIdentifierKey.HeartRate. En función del estado devuelto, la aplicación habilita o deshabilita la capacidad de escribir datos. No hay experiencia de usuario estándar para tratar con una denegación de acceso y hay muchas opciones posibles. En la aplicación de ejemplo, el estado se establece en un objeto singleton HeartRateModel que, a su vez, genera eventos pertinentes.

Modelo, vista y controlador

Para revisar el objeto singleton HeartRateModel, abra el archivo 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()));
                                                }
                                        });
                                });
                        }
                }
        }
}

La primera sección es código reutilizable para crear eventos y controladores genéricos. La parte inicial de la clase HeartRateModel también es reutilizable para crear un objeto singleton seguro para subprocesos.

A continuación, HeartRateModel expone 3 eventos:

  • EnabledChanged: indica que el almacenamiento de frecuencia cardíaca se ha habilitado o deshabilitado (tenga en cuenta que el almacenamiento está deshabilitado inicialmente).
  • ErrorMessageChanged: para esta aplicación de ejemplo, tenemos un modelo de control de errores muy sencillo: una cadena con el último error.
  • HeartRateStored: se genera cuando se almacena una frecuencia cardíaca en la base de datos de Health Kit.

Tenga en cuenta que cada vez que se desencadenan estos eventos, se realiza a través de NSObject.InvokeOnMainThread(), lo que permite a los suscriptores actualizar la interfaz de usuario. Como alternativa, los eventos se podrían documentar como generados en subprocesos en segundo plano y la responsabilidad de garantizar la compatibilidad podría dejarse a sus controladores. Las consideraciones sobre subprocesos son importantes en las aplicaciones de Health Kit porque muchas de las funciones, como la solicitud de permisos, son asincrónicas y ejecutan sus devoluciones de llamada en subprocesos no principales.

El código específico del Health Kit en HeartRateModel está en las dos funciones HeartRateInBeatsPerMinute() y StoreHeartRate().

HeartRateInBeatsPerMinute() convierte su argumento en un Health Kit HKQuantity fuertemente tipado. El tipo de la cantidad es el especificado por HKQuantityTypeIdentifierKey.HeartRate y las unidades de la cantidad son HKUnit.Count dividido por HKUnit.Minute (en otras palabras, la unidad es pulsaciones por minuto).

La función StoreHeartRate() toma un HKQuantity (en la aplicación de ejemplo, uno creado por HeartRateInBeatsPerMinute()). Para validar sus datos, usa el método HKQuantity.IsCompatible(), que devuelve true si las unidades del objeto se pueden convertir en las unidades del argumento. Si la cantidad se creó con HeartRateInBeatsPerMinute() obviamente devolverá true, pero también devolverá true si la cantidad se creó como, por ejemplo, Latidos por hora. Más comúnmente, HKQuantity.IsCompatible() se puede usar para validar la masa, la distancia y la energía que el usuario o un dispositivo podrían introducir o mostrar en un sistema de medida (como unidades imperiales), pero que podrían almacenarse en otro sistema (como unidades métricas).

Una vez validada la compatibilidad de la cantidad, se utiliza el Factory Method HKQuantitySample.FromType() para crear un objeto heartRateSample fuertemente tipado. Los objetos HKSample tienen una fecha de inicio y finalización; para lecturas instantáneas, estos valores deben ser los mismos que en el ejemplo. El ejemplo tampoco establece ningún dato de clave-valor en su argumento HKMetadata, pero se podría usar código como el siguiente para especificar la ubicación del sensor:

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

Una vez creado heartRateSample, el código crea una nueva conexión a la base de datos con el bloque using. Dentro de ese bloque, el método HKHealthStore.SaveObject() intenta la escritura asincrónica en la base de datos. La llamada resultante a la expresión lambda desencadena eventos relevantes, ya sea HeartRateStored o ErrorMessageChanged.

Ahora que el modelo se ha programado, es el momento de ver cómo el controlador refleja el estado del modelo. Abra el archivo HKWorkViewController.cs. El constructor simplemente asocia el singleton HeartRateModel a los métodos de control de eventos (de nuevo, esto podría hacerse en línea con expresiones lambda, pero los métodos independientes hacen que la intención sea un poco más obvia):

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

Estos son los controladores pertinentes:

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);
}

Obviamente, en una aplicación con un único controlador, sería posible evitar la creación de un objeto de modelo independiente y el uso de eventos para el flujo de control, pero el uso de objetos de modelo es más adecuado para las aplicaciones reales.

Ejecución de la aplicación de ejemplo

El simulador de iOS no admite el Health Kit. La depuración debe realizarse en un dispositivo físico que ejecute iOS 8.

Conecte un dispositivo de desarrollo iOS 8 aprovisionado correctamente al sistema. Selecciónelo como destino de implementación en Visual Studio para Mac y, en el menú, elija Ejecutar > Depurar.

Importante

Los errores relacionados con el aprovisionamiento se mostrarán en este momento. Para solucionar errores, revise la sección Creación y aprovisionamiento de una aplicación de Health Kit anterior. Los componentes son:

  • Centro de desarrollo de iOS : identificador de aplicación explícito y perfil de aprovisionamiento habilitado para Health Kit.
  • Opciones de proyecto: identificador de lote (identificador de aplicación explícito) y perfil de aprovisionamiento.
  • Código fuente: Entitlements.plist e Info.plist

Suponiendo que las disposiciones se hayan establecido correctamente, se iniciará la aplicación. Cuando llegue a su método OnActivated, solicitará la autorización de Health Kit. La primera vez que el sistema operativo encuentre esto, se mostrará al usuario el siguiente cuadro de diálogo:

Se mostrará al usuario este cuadro de diálogo

Habilite la aplicación para actualizar los datos de frecuencia cardíaca y la aplicación volverá a aparecer. La devolución de llamada ReactToHealthCarePermissions se activará de forma asincrónica. Esto hará que la HeartRateModel’s Enabled propiedad cambie, lo que provocará el EnabledChanged evento, lo que hará que el HKPermissionsViewController.OnEnabledChanged() controlador de eventos se ejecute, lo que habilita el StoreData botón. En el diagrama siguiente se muestra la secuencia:

En este diagrama se muestra la secuencia de eventos

Presione el botón Grabar. Esto hará que se ejecute el controlador StoreData_TouchUpInside(), que intentará analizar el valor del campo de texto heartRate, convertirlo en HKQuantity mediante la función HeartRateModel.HeartRateInBeatsPerMinute() anteriormente comentada y pasar esa cantidad a HeartRateModel.StoreHeartRate(). Como se ha explicado anteriormente, este intentará almacenar los datos y generará un evento HeartRateStored o ErrorMessageChanged.

Haga doble clic en el botón Inicio del dispositivo y abra la aplicación Salud. Haga clic en la pestaña Orígenes y verá que aparece la aplicación de ejemplo. Selecciónela y desactive el permiso para actualizar los datos de frecuencia cardíaca. Haga doble clic en el botón Inicio y vuelva a la aplicación. Una vez más, se llamará a ReactToHealthCarePermissions() pero esta vez, debido a que el acceso está denegado, el botón StoreData se desactivará (tenga en cuenta que esto ocurre de forma asíncrona y el cambio en la interfaz de usuario puede ser visible para el usuario final).

Temas avanzados

La lectura de datos de la base de datos del Health Kit es muy similar a la escritura de datos: se especifican los tipos de datos a los que se intenta acceder, se solicita autorización y, si esta se concede, los datos están disponibles, con conversión automática a unidades de medida compatibles.

Hay una serie de funciones de consulta más sofisticadas que permiten realizar consultas basadas en predicciones y consultas que realizan actualizaciones cuando se actualizan los datos pertinentes.

Los desarrolladores de aplicaciones de Health Kit deben revisar la sección Health Kit de las directrices de revisión de aplicaciones de Apple.

Una vez que se comprendan los modelos de seguridad y de sistema de tipos, almacenar y leer datos en la base de datos de Health Kit compartida es bastante sencillo. Muchas de las funciones de Health Kit funcionan de forma asincrónica y los desarrolladores de aplicaciones deben escribir sus programas de forma adecuada.

En el momento de escribir este artículo, no existe un equivalente a Health Kit en Android o Windows Phone.

Resumen

En este artículo hemos visto cómo Health Kit permite a las aplicaciones almacenar, recuperar y compartir información relacionada con la salud, al tiempo que proporciona una aplicación de salud estándar que permite al usuario acceder a estos datos y controlarlos.

También hemos visto cómo la privacidad, la seguridad y la integridad de los datos son preocupaciones primordiales para la información relacionada con la salud, y las aplicaciones que utilizan Health Kit deben hacer frente al aumento de la complejidad en los aspectos de administración de aplicaciones (aprovisionamiento), codificación (sistema de tipos de Health Kit) y experiencia de usuario (control de permisos por parte del usuario a través de los diálogos del sistema y la aplicación Salud).

Por último, hemos visto una implementación sencilla de Health Kit mediante la aplicación de ejemplo incluida que escribe los datos de los latidos del corazón en el almacén de Health Kit y tiene un diseño asíncrono.