En este artículo de HealthKit, aprenderá a solicitar permiso para acceder a los datos de HealthKit, así como a leer y escribir datos en el repositorio central de HealthKit. El artículo utiliza Swift 4, iOS 11, versión Xcode 9.
HealthKit es una API que se introdujo en iOS 8.
HealthKit sirve como el depósito central de todos los datos relacionados con la salud, lo que permite a los usuarios crear un perfil biológico y almacenar datos de entrenamiento.
A medida que lea el artículo de HealthKit, creará la aplicación de seguimiento de capacitación más simple y aprenderá:
- Cómo solicitar permiso y acceder a los datos de HealthKit
- Cómo leer datos de HealthKit y mostrarlos en un UITableView
- Cómo escribir datos en el repositorio central de HealthKit
¿Listo para comenzar con HealthKit? Sigue leyendo!
Nota: Para trabajar en este tutorial, necesitará una cuenta de desarrollador de iOS activa. Sin esto, no puede habilitar la capacidad de HealthKit y obtener acceso al repositorio de HealthKit.Inicio
La aplicación de inicio rastrea la quema de calorías durante un programa de entrenamiento. Para los conocedores de Hollywood y los socialites, debería ser obvio que estoy hablando de
Prancercise .
Descargue el proyecto de inicio y ábralo en Xcode .
Compila y ejecuta la aplicación. Verá el "esqueleto" de la interfaz de usuario. En los próximos dos artículos, agregará gradualmente funcionalidad para esta aplicación.
Asignando un equipo
HealthKit es un marco especial. La aplicación no podrá usarla si no tiene una cuenta de desarrollador activa. Después de tener una cuenta de desarrollador, puede asignar su equipo.
Seleccione
PrancerciseTracker en el Navegador de proyectos y luego seleccione el
objetivo PrancerciseTracker . Vaya a la pestaña
General y haga clic en el campo
Equipo .
Seleccione el comando asociado con su cuenta de desarrollador:
Permisos / Derechos
HealthKit también tiene su propio conjunto de derechos, y deberá habilitarlos para crear aplicaciones que usen el marco.
Abra la pestaña
Capacidades en el editor de destino y habilite
HealthKit , como se muestra en la siguiente captura de pantalla:

Espere a que Xcode configure HealthKit por usted. Como regla, no hay problemas aquí, pero aún puede encontrar algunos si olvida especificar correctamente el Identificador de equipo y de paquete.
Ahora todo está listo. Solo necesita pedirle al usuario permiso para usar HealthKit.
Permisos
HealthKit trabaja con datos confidenciales y confidenciales. No todos se sienten tan cómodos como para permitir que las aplicaciones instaladas accedan a esta información.
Es por eso que HealthKit tiene un fuerte sistema de privacidad. HealthKit solo tiene acceso a los datos que los usuarios aceptan compartir. Para crear un perfil para los usuarios de su Prancercise Tracker, primero debe obtener permiso para acceder a cada tipo de datos.
Uso Descripción Actualización
Primero, debe describir por qué está solicitando indicadores de salud a sus usuarios.
Xcode le permite especificar esto en el archivo
Info.plist de su aplicación.
Abrir
Info.plist . Luego agregue las siguientes claves:
Privacidad -
Descripción del uso de Health SharePrivacidad :
descripción del uso de la actualización de estadoEstas teclas almacenan el texto que se mostrará cuando aparezca la pantalla de inicio de sesión de HeathKit.
La Descripción del uso de Health Share se refiere a la sección de datos que debe leerse de HealthKit.
La Descripción del uso de la actualización de estado corresponde a los datos que se escriben en HealthKit.
Puedes "agregar" todo lo que quieras allí. Esta suele ser una descripción: "Utilizaremos su información de salud para realizar un mejor seguimiento de sus entrenamientos".
Tenga en cuenta que si estas claves no están instaladas, la aplicación se bloqueará cuando intente iniciar sesión en HealthKit.
Autorización de HealthKit
Abra el archivo
HealthKitSetupAssistant.swift dentro del cual se encuentra el método de clase que utilizará para autorizar en HealthKit.
class func authorizeHealthKit(completion: @escaping (Bool, Error?) -> Swift.Void) { }
El método authorizeHealthKit (finalización :) no toma parámetros y tiene un
complemento que devuelve un valor booleano (
éxito o
error ) y un error opcional en caso de que algo salga mal. Si se devuelven errores, los pasará a completar en dos casos:
- HealthKit puede no estar disponible en su dispositivo. Por ejemplo, si la aplicación se ejecuta en un iPad.
- Es posible que algunos tipos de datos no estén disponibles en la versión actual de HealthKit.
Rompamos este proceso. Para autorizar HealthKit, el método
authorizeHealthKit (complete :) debe completar los siguientes cuatro pasos:
- Compruebe si Healthkit está disponible en este dispositivo. Si este no es el caso, devuelva una falla y un error para completar.
- Preparar tipos de datos de salud. Prancercise Tracker leerá y escribirá en HealthKit.
- Organice estos datos en una lista de tipos para leer y tipos para escribir.
- Solicitar autorización. Si esta acción es exitosa, entonces todas las actividades fueron correctas y se completaron correctamente.
Comprobación de disponibilidad de HealthKit
En primer lugar, debe verificar la disponibilidad de HealthKit en el dispositivo.
Pegue el siguiente código al comienzo del método
authorizeHealthKit (finalización :) :
Interactuará con
HKHealthStore muy a menudo. Es un repositorio central que almacena datos de salud del usuario. El método
isHealthDataAvailable () lo ayudará a comprender si el dispositivo de usuario actual admite datos de Heathkit.
La declaración de protección evita que la aplicación ejecute el resto del método
authorizeHealthKit (finalización :) si HealthKit no está disponible en el dispositivo. Cuando esto sucede, se
llama al bloque de finalización con el error
notAvailableOnDevice . Simplemente puede enviar esto a la consola o al controlador principal para procesar pasos adicionales en caso de tal error.
Preparación de datos
Una vez que sepa que HealthKit está disponible en el dispositivo del usuario, es hora de preparar los tipos de datos que se leerán y escribirán en HealthKit.
HealthKit funciona con el tipo
HKObjectType . Cada tipo que ingresa o regresa al repositorio central de HealthKit es un tipo de
HKObjectType . También verá HKSampleType y
HKWorkoutType . Ambos heredan de
HKObjectType , así que básicamente esto es lo mismo.
Pegue el siguiente fragmento de código inmediatamente después del primer fragmento de código:
Wow, esta es una gran
guardia ! Este también es un gran ejemplo del uso de un solo protector para recuperar múltiples opciones.
Para crear un
HKObjectType para estas características, debe usar
HKObjectType.characteristicType (forIdentifier :) o
HKObjectType.quantityType (forIdentifier :)Los tipos de características y los tipos de cantidad son enumeraciones definidas por el marco. HealthKit arranca con ellos.
También notará que si una característica o tipo de selección no está disponible, el método fallará. Esto es intencional Su aplicación siempre debe saber exactamente con qué tipos de HealthKit puede funcionar, si corresponde.
Preparar una lista de tipos de datos para leer y escribir
Ahora es el momento de preparar una lista de tipos de datos para leer y escribir.
Pegue este tercer código en el método
authorizeHealthKit (finalización :) inmediatamente después de la segunda parte:
HealthKit espera un conjunto de objetos
HKSampleType que representan los tipos de datos que su usuario puede escribir, y también espera que se muestre un conjunto de objetos HKObjectType para su aplicación.
HKObjectType.workoutType () es un tipo especial de
HKObjectType . Es cualquier entrenamiento.
Autorización de HealthKit
La última parte es la más fácil. Solo necesita solicitar autorización de HealthKit. Pegue este último código:
Este código solicita autorización de HealthKit y luego llama a la finalización. Utilizan variables para operaciones exitosas y errores pasados del método
requestAuthorization (toShare: read: complete :) de HKHealthStore .
Puedes pensarlo como una redirección. En lugar de manejar la finalización dentro de HealthKitSetupAssistant, pasa el paquete al controlador principal, que puede mostrar una advertencia o tomar alguna otra medida.
El proyecto ya tiene un botón Authorize HealthKit y llama al método
authorizeHealthKit () en MasterViewController. Este es el lugar perfecto para llamar al método de autorización que acabamos de escribir.
Abra
MasterViewController.swift , busque el método
authorizeHealthKit ( ) y pegue este código:
HealthKitSetupAssistant.authorizeHealthKit { (authorized, error) in guard authorized else { let baseMessage = "HealthKit Authorization Failed" if let error = error { print("\(baseMessage). Reason: \(error.localizedDescription)") } else { print(baseMessage) } return } print("HealthKit Successfully Authorized.") }
Este código utiliza el método
authorizeHealthKit (finalización :) que acaba de implementar. Cuando se complete, mostrará un mensaje en la consola para indicar si la autorización se realizó correctamente en HealthKit.
Inicia la aplicación. Haga clic en Autorizar HealthKit en la ventana principal y verá una pantalla de autorización emergente:
Active todos los interruptores, desplácese para verlos todos y presione
Permitir . En la consola, debería ver un mensaje como este:
HealthKit Successfully Authorized.
Genial La aplicación tiene acceso al repositorio central de HealthKit. Ahora es el momento de comenzar a rastrear elementos.
Características y muestras
En esta sección aprenderás:
- Cómo leer las características biológicas de tu usuario.
- Cómo leer y escribir diferentes tipos de muestras (peso, altura, etc.)
Las características biológicas, como regla, son tipos de elementos que no cambian, al igual que su tipo de sangre. Las muestras son elementos que cambian con frecuencia, como el peso.
Para realizar un seguimiento adecuado de la efectividad del
modo de entrenamiento
Prancercise , la aplicación
Prancercise Tracker debe recibir una muestra del peso y la altura del usuario. Juntas, estas muestras se pueden usar para calcular el índice de masa corporal (IMC).
Nota: El índice de masa corporal (IMC) es un indicador ampliamente utilizado de la grasa corporal y se calcula en función del peso y la altura de una persona. Obtenga más información al respecto aquí .Especificaciones de lectura
Prancercise Tracker no registra características biológicas. Los obtiene de HealthKit. Esto significa que estas características deben almacenarse primero en el repositorio central de HeathKit.
Si aún no lo ha hecho, es hora de contarle a
HeathKit un poco más sobre usted.
Abra la aplicación Health en su dispositivo o simulador. Seleccione la pestaña Datos de salud. Luego haga clic en el icono de perfil en la esquina superior derecha para ver su perfil de salud. Haga clic en
Editar e ingrese la fecha de nacimiento, género, tipo de sangre:
Ahora que
HealthKit conoce su fecha de nacimiento, sexo y tipo de sangre, es hora de leer estas características en
Prancercise Tracker .
Regrese a
Xcode y abra
ProfileDataStore.swift . La clase
ProfileDataStore representa su punto de acceso a todos los datos relacionados con la salud de sus usuarios.
Pegue el siguiente método en
ProfileDataStore :
class func getAgeSexAndBloodType() throws -> (age: Int, biologicalSex: HKBiologicalSex, bloodType: HKBloodType) { let healthKitStore = HKHealthStore() do {
El método
getAgeSexAndBloodType () llama a
HKHealthStore , solicitando la fecha de nacimiento, el género y el tipo de sangre del usuario. También calcula la edad del usuario utilizando la fecha de nacimiento.
- Es posible que haya notado que este método puede causar un error. Esto sucede cuando una fecha de nacimiento, sexo o tipo de sangre no se ha almacenado en el repositorio central de HealthKit. Como acaba de ingresar esta información en su aplicación, no debe causar errores.
- Usando la clase Calendario , puede convertir cualquier fecha en un conjunto de Componentes de fecha . Esto es realmente conveniente cuando desea obtener un año para una cita. Este código solo obtiene su año de nacimiento, el año actual y luego calcula la diferencia.
- Las variables "expandidas" se nombran de tal manera que está claro que necesita acceder a la enumeración base desde la clase contenedora ( HKBiologicalSexObject y HKBloodTypeObject ).
Actualización de la interfaz de usuario
Si ahora compila y ejecuta la aplicación, no verá ningún cambio en la interfaz de usuario, porque todavía no le ha conectado esta lógica.
Abra
ProfileViewController.swif t y busque el método
loadAndDisplayAgeSexAndBloodType ( )
Este método usará su
ProfileDataStore para cargar características biológicas en la interfaz de usuario.
Pegue el siguiente código en el método
loadAndDisplayAgeSexAndBloodType () :
do { let userAgeSexAndBloodType = try ProfileDataStore.getAgeSexAndBloodType() userHealthProfile.age = userAgeSexAndBloodType.age userHealthProfile.biologicalSex = userAgeSexAndBloodType.biologicalSex userHealthProfile.bloodType = userAgeSexAndBloodType.bloodType updateLabels() } catch let error { self.displayAlert(for: error) }
Este bloque de código carga la edad, el género y el tipo de sangre como una tupla. Luego establece estos campos en la instancia local del modelo UserHealthProfile. Finalmente, actualiza la interfaz de usuario con los nuevos campos en
UserHealthProfile llamando al método
updateLabels () .
Dado que el
método ProfileDataStore getAgeSexAndBloodType () puede arrojar un error,
ProfileViewController debe manejarlo. En este caso, simplemente toma el error y lo presenta como una advertencia.
Todo esto es genial, pero hay una trampa. El método
updateLabels () no hace nada todavía. Esto es solo un anuncio en blanco. Esta vez, pasemos a la interfaz de usuario.
Encuentre el método
updateLabels () y pegue este código en él:
if let age = userHealthProfile.age { ageLabel.text = "\(age)" } if let biologicalSex = userHealthProfile.biologicalSex { biologicalSexLabel.text = biologicalSex.stringRepresentation } if let bloodType = userHealthProfile.bloodType { bloodTypeLabel.text = bloodType.stringRepresentation }
El código es bastante simple. Si el usuario ha establecido la edad, se formateará en una etiqueta. Lo mismo ocurre con el sexo biológico y el tipo de sangre. La variable stringRepresentation convierte la enumeración en una cadena para fines de visualización.
Compila y ejecuta la aplicación. Vaya a la pantalla Perfil e IMC. Haga clic en el botón Leer datos de HealthKit.
Si ya ingresó su información en la aplicación, debería aparecer en los accesos directos en esta pantalla. Si no lo ha hecho, aparecerá un mensaje de error.
Wow! Usted lee y muestra datos directamente desde
HealthKit .
Consultar muestras
Ahora es el momento de leer el peso y la altura del usuario. Se utilizarán para calcular y mostrar el IMC en la vista de perfil.
Las características biológicas están disponibles porque casi nunca cambian. Las muestras requieren un enfoque mucho más complejo. Usan
HKQuery , más precisamente
HKSampleQuery .
Para solicitar muestras de HealthKit, necesitará:
- Especifique el tipo de muestra que desea solicitar (peso, altura, etc.),
- Algunas opciones adicionales que ayudan a filtrar y ordenar datos. Para hacer esto, puede pasar un NSPredicate opcional o una matriz de NSSortDescriptors .
Nota: Si está familiarizado con CoreData, probablemente haya notado algunas similitudes. HKSampleQuery es muy similar a NSFetchedRequest para un tipo de objeto, donde especifica el predicado y los descriptores de clasificación, y luego establece el contexto del objeto para ejecutar la consulta para obtener los resultados.Una vez que su consulta está configurada, simplemente llame al
método HKHealthStore ExecuteQuery () para obtener los resultados.
Para
Prancercise Tracker, creará una función única y universal que descarga las últimas muestras de cualquier tipo. Por lo tanto, puede usarlo tanto para peso como para altura.
Abra
ProfileDataStore.swift y pegue el siguiente método en la clase, justo debajo del método
getAgeSexAndBloodType () :
class func getMostRecentSample(for sampleType: HKSampleType, completion: @escaping (HKQuantitySample?, Error?) -> Swift.Void) {
Este método usa el tipo de muestra (altura, peso, IMC, etc.). Luego crea una consulta para recuperar la última muestra para este tipo. Si revisa el tipo de muestra de crecimiento, volverá a su último registro de crecimiento.
Están pasando muchas cosas aquí. Me detendré para explicar algunas cosas.
- Hay varios métodos en HKQuery que pueden ayudarlo a filtrar los ejemplos de consultas de HealthKit. En este caso, usamos el predicado de fecha incorporado.
- Solicitar muestras de HealthKit es un proceso asincrónico. Es por eso que el código en el controlador de finalización se produce dentro del bloque Dispatch. Se requiere cumplimiento en el hilo principal. Si no lo hace, la aplicación fallará.
Si todo va bien, su solicitud se ejecutará y obtendrá una muestra ordenada devuelta en el hilo
principal , donde
ProfileViewController puede poner su contenido en la etiqueta. Hagamos esta parte ahora.
Mostrar muestras en la interfaz de usuario
En la sección anterior, descargó datos de
HealthKit .
Guárdelos como modelo en
ProfileViewController y luego actualice el contenido en filas con el
método ProfileViewController updateLabels ()Todo lo que tiene que hacer es expandir este proceso agregando una función que carga las muestras, las procesa para la interfaz de usuario y luego llama a
updateLabels () para llenar las etiquetas con texto.
Abra el archivo
ProfileViewController.swift , busque el método
loadAndDisplayMostRecentHeight ( ) y pegue el siguiente código:
- Este método comienza creando un tipo de muestra de crecimiento. Luego pasa este tipo de muestra al método que acaba de escribir, que devolverá la muestra de crecimiento de usuarios más reciente registrada en HealthKit.
- Tan pronto como la muestra regrese, el crecimiento se convierte a metros y se almacena en el modelo de Perfil de usuario de salud. Entonces la IU se actualizará.
Nota: Por lo general, desea convertir una muestra de cantidad en una unidad estándar. Para hacer esto, el código anterior usa el método doubleValue (for :) , que le permite pasar los datos relevantes que necesita (en este caso, metros) a HKUnit .
Puede crear varios tipos de HKUnits utilizando algunos de los métodos de clase comunes disponibles a través de HealthKit . Para obtener contadores, simplemente puede usar el método meter () en HKUnit , y eso será lo que necesita.Con el crecimiento resuelto. ¿Qué tal el peso? Todo es bastante similar, pero deberá
completar el método
loadAndDisplayMostRecentWeight () en
ProfileViewController .
Pegue el siguiente código en el método
loadAndDisplayMostRecentWeight () :
guard let weightSampleType = HKSampleType.quantityType(forIdentifier: .bodyMass) else { print("Body Mass Sample Type is no longer available in HealthKit") return } ProfileDataStore.getMostRecentSample(for: weightSampleType) { (sample, error) in guard let sample = sample else { if let error = error { self.displayAlert(for: error) } return } let weightInKilograms = sample.quantity.doubleValue(for: HKUnit.gramUnit(with: .kilo)) self.userHealthProfile.weightInKilograms = weightInKilograms self.updateLabels() }
Cree el tipo de muestra que desea recibir, solicite
HealthKit , realice algunas conversiones de unidades, guárdelo en su modelo y actualice la interfaz de usuario.
Por el momento, puede mostrar que el trabajo está hecho, pero hay algo más. La función
updateLabels () no tiene conocimiento de los nuevos datos que ha puesto a su disposición.
Vamos a arreglarlo
Agregue las siguientes líneas a la función
updateLabels () , justo debajo de la parte donde expande el grupo sanguíneo para mostrarlo en la interfaz de usuario:
if let weight = userHealthProfile.weightInKilograms { let weightFormatter = MassFormatter() weightFormatter.isForPersonMassUse = true weightLabel.text = weightFormatter.string(fromKilograms: weight) } if let height = userHealthProfile.heightInMeters { let heightFormatter = LengthFormatter() heightFormatter.isForPersonHeightUse = true heightLabel.text = heightFormatter.string(fromMeters: height) } if let bodyMassIndex = userHealthProfile.bodyMassIndex { bodyMassIndexLabel.text = String(format: "%.02f", bodyMassIndex) }
Siguiendo la plantilla original en la función
updateLabels () , expande la altura, el peso y el índice de masa corporal en su modelo
UserHealthProfile . Si están disponibles, generan las líneas apropiadas y las asignan a etiquetas en la pantalla del usuario.
MassFormatter y
LengthFormatter hacen el trabajo de convertir sus valores en cadenas.
El índice de masa corporal no se almacena realmente en el modelo de
perfil de usuario de salud . Esta es una propiedad calculada que hace el cálculo por usted.
Haga clic en la propiedad
bodyMassIndex y verá lo que quiero decir:
var bodyMassIndex: Double? { guard let weightInKilograms = weightInKilograms, let heightInMeters = heightInMeters, heightInMeters > 0 else { return nil } return (weightInKilograms/(heightInMeters*heightInMeters)) }
El índice de masa corporal es una propiedad opcional, es decir, puede devolver nulo si no especificó altura o peso (o si se establecen en algún número que no tiene sentido). El cálculo real es simplemente el peso dividido por la altura al cuadrado.
Nota: Pronto se sumergirá en todo esto si no ha agregado datos a HealthKit para que la aplicación los lea. Si aún no lo ha hecho, debe crear muestras de altura y peso, al menos.Abra la aplicación Salud y vaya a la pestaña Datos de salud. Allí, seleccione el parámetro Mediciones del cuerpo, luego seleccione Peso y luego Agregar punto de datos para agregar una nueva muestra de peso. Repita el proceso para el crecimiento.En este punto, el Prancercise Tracker debería poder leer una muestra reciente del peso y la altura de su usuario, y luego mostrarla en el texto.Compila y ejecuta las aplicaciones. Vaya a Perfil e IMC . Luego haga clic en el botón Leer datos de HealthKit .Impresionante! Acabas de leer tus primeras muestras del repositorio de HealthKit y las usaste para calcular el IMC.Guardar muestras
En Prancercise rastreador ya tiene un índice de masa corporal calculadora a mano. Usémoslo para registrar la muestra de IMC de su usuario.Abra ProfileDataStore.swift y agregue el siguiente método: class func saveBodyMassIndexSample(bodyMassIndex: Double, date: Date) {
Al igual que con otros tipos de muestra, primero debe asegurarse de que el tipo de muestra esté disponible en HealthKit .- En este caso, el código verifica si existe un tipo de cantidad para el índice de masa corporal. Si es así, se usa para crear una muestra de cantidad. Si no, la aplicación deja de funcionar.
- count() HKUnit , , . - , , .
- HKHealthStore , . , .
Casi terminado Para resumir la interfaz de usuario.Abra ProfileViewController.swif , busque el método saveBodyMassIndexToHealthKit ( ). Se llama a este método cuando el usuario hace clic en el botón Guardar IMC en la tabla.Pegue el siguiente código en el método: guard let bodyMassIndex = userHealthProfile.bodyMassIndex else { displayAlert(for: ProfileDataError.missingBodyMassIndex) return } ProfileDataStore.saveBodyMassIndexSample(bodyMassIndex: bodyMassIndex, date: Date())
Recuerde que el índice de masa corporal es una propiedad calculada que devuelve un valor cuando las muestras de altura y peso se cargan desde HealthKit . Este código está tratando de calcular esta propiedad y, si es posible, se pasará al método saveBodyMassIndexSample (bodyMassIndex: date :) que acaba de escribir.También muestra una alerta conveniente si el índice de masa corporal no puede calcularse por algún motivo.Compila y ejecuta la aplicación. Vaya a la pantalla Perfil e IMC . Descargue datos de HeathKit , luego haga clic en el botón Guardar IMC.Mira la consola Lo ves BMI
Si es así, ¡felicidades! Su muestra de IMC ahora está almacenada en el repositorio central de HealthKit . A ver si podemos encontrarlo.Abra la aplicación Salud, toque la pestaña Datos de salud, haga clic en Mediciones corporales en la vista de tabla y luego haga clic en Índice de masa corporal.