¿Cómo crear tu primera app en iPhone y Apple Watch?
Aprende a crear tu primera app para tu Apple Watch. Aprendemos a crear un contador de pasos usando el framework HealthKit. Crea una app iOS y reutiliza tu código en tu app watchOS, lo único que necesitas es crear un módulo (con Swift Package Manager) y compartir la lógica y vistas.
Tabla de contenido
Hoy en SwiftBeta vamos a ver un post muy potente. En el sentido de que vamos a crear una app muy sencilla para nuestro iPhone que nos muestre los pasos que hemos realizado durante el día. Y lo siguiente que haremos será crear la misma app en nuestro Apple Watch. Para hacerlo crearemos un módulo con Swift Package Manager y extraeremos la lógica utilizada en nuestra app para iPhone y así la reutilizaremos en nuestro Apple Watch. ¿El beneficio de esto? reusaremos la misma lógica en lugar de duplicar código.
Creamos nuestra iOS app
Abrimos Xcode y creamos una app iOS.
Le ponemos nombre, en mi caso la voy a llamar ContadorDePasos
Añadimos HealthKit en Capabilities
Lo primero de todo que vamos hacer es irnos a la sección de Signing & Capabilities y allí vamos a añadir HealthKit. (Es necesario hacer este paso para poder obtener la información)
Una vez añadido ya podemos empezar a escribir código!
Creamos el ViewModel
Lo siguiente que vamos hacer es crear un fichero nuevo, vamos a crear un ViewModel y vamos a añadir la siguiente lógica:
- Hemos importado el framework HealthKit. Lo necesitamos para poder extraer los pasos realizados durante un período de tiempo concreto. En nuestro caso vamos a sacar los pasos realizados durante un día.
- Tenemos que pedir acceso al user para que nos permita obtener esta información. Es por eso que si tenemos datos disponibles, lo que haremos será pedir autorización a un user para indicar que queremos acceder al número de pasos. Aquí podríamos acceder a otro tipo de información (como distancia que hemos caminado, nuestro peso, ritmo cardiaco, etc), pero en nuestro caso solo accederemos al número de pasos.
Una vez tenemos este código implementado, queremos que cuando un user accepta la autorización, se obtenga esta información, por lo tanto vamos a crear un método que será llamado desde dentro del closure de requestAuthorization
Lo siguiente que vamos hacer es crear este método, va a ser el encargado de escuchar cambios en los datos de nuestros pasos, cuando hagamos más pasos este método tendrá una lógica para refrescar nuestra información. Nuestro código quedaría de la siguiente manera:
Hemos creado un método nuevo con un HKObserverQuery que trigeará el contenido de su closure cada vez que se detecten nuevos pasos. Y cada vez que se tengamos nuevos datos, llamaremos a un nuevo método lo vamos a llamar getMySteps()
- Lo único que hemos hecho ha sido seleccionar el tipo de datos que queremos obtener, en nuestro caso solo pasos.
- Hemos creado un rango de tiempo para sacar esta información, en nuestro caso es lo que llevamos de día.
- Creamos una query para obtener esta información
- Una vez obtenemos la información lo que hacemos es sumar estos datos y lo asignamos a una nueva propiedad @Published llamada allMySteps. Que nos servirá para refrescar nuestra vista.
- Ejecutamos la query
Creamos la vista
Una vez hemos creado los métodos necesarios en nuestro ViewModel, nos vamos a nuestro ContentView. Y vamos a crear la siguiente vista:
Ahora antes de compilar nuestra app vamos a añadir una Key en nuestro Info.plist. Necesitamos añadir la key Privacy - Health Share Usage Description y darle un texto. El motivo es que cuando pedimos autorización para obtener los datos sobre salud de nuestro iPhone, necesitamos mostrar un Alert pidiendo permiso al user, en ese alert debe aparecer un mensaje, el que queramos, pero debemos especificarlo sí o sí.
En mi caso, he añadido el mensaje: Hola! queremos acceder al número de pasos que has realizado a lo largo de hoy.
Vamos a compilar a ver qué ocurre.
Una vez lanzamos nuestra app, automáticamente vemos cómo aparece la pantalla de la imagen anterior, debemos aceptar para que nuestra app pueda acceder a la información especificada. En nuestro caso van a ser solo los pasos, pero podría ser mucha más información.
Si te fijas, también aparece el mensaje de Hola! queremos acceder al número de pasos que has realizado a lo largo de hoy.
Y una vez aceptado que nuestra app accederá a los datos de Salud, nos aparece la vista de nuestra app con la información de los pasos que hemos realizado en el día de hoy.
La imagen que os muestro a continuación es de la compilación que he hecho de mi app en mi iPhone, pero si lo hacéis en vuestro simulador, debereís añadir esta información manual. ¿Por qué? en mi iPhone tengo información que se va almacenando en la app Health, pero en el simulador nadie está nutriendo con datos la app Healtch, es por eso que lo podemos hacer de forma manual.
Si por ejemplo, habéis compilado la app en un dispositivo físico real, y empezáis a caminar, podréis ver como el número de pasos aumentan (el cambio no es inmediato, se tarda unos segundos en ver el cambio).
Ahora vamos a crear nuestra app en el Apple Watch
Mostramos los pasos en el Apple Watch
Ahora, sin salir de Xcode vamos a crear la app para el Apple Watch, lo que vamos hacer es crear una extensión creando un target nuevo. Nos vamos a File -> New -> Target.
Allí escogemos:
- Multiplatorm: watchOS
- Application: Watch App for iOS App
Le damos a Next y añadimos un nombre a nuestro nuevo Target. En mi caso voy a poner ContadorDePasosWatch.
Una vez lo tenemos creado, veremos en nuestro listado de ficheros que se han añadido más carpetas y ficheros. Estos pertenecen al target de la app que acabamos de crear para el Apple Watch.
Nosotros, ahora lo que queremos hacer es acceder a la lógica de nuestro ViewModel, pero ¿qué pasa? está en nuestra app principal. ¿Cómo podemos acceder a los métodos de nuestro ViewModel? podríamos copiar y pegar nuestro ViewModel en el target del Apple Watch, pero no es una buena solución.
Lo que vamos hacer es crear un módulo, y la lógica que añadamos allí nos servirá para utilizar en multiples partes de nuestra app. Sin necesidad de duplicar código.
Creamos un módulo con Swift Package Manager
Para crear un módulo nos vamos a File -> New -> Package
Nos aparecerá una ventana para que indiquemos el nombre de nuestro módulo y dónde lo queremos añadir. En nuestro caso, vamos a guardarlo en la misma carpeta que nuestra app y vamos a seleccionar:
- Add to: ContadorDePasos (en nuestra app, quizás las has llamado diferente)
- Group: ContadorDePasos (en nuestra app, quizás las has llamado diferente)
Y una vez le damos a Create vemos como aparece en nuestro listado de ficheros de Xcode.
Lo que vamos hacer es copiar el ViewModel de nuestra app y lo vamos a pegar dentro de la carpeta Source de nuestro módulo, en el fichero llamado StepsModule
Lo siguiente que vamos hacer, es marcar como public los métodos que necesitemos acceder desde nuestra app. También crearemos un método init público para que se pueda instanciar nuestro ViewModel desde fuera de su módulo:
Una vez hemos hecho esto, nos vamos a nuestro fichero Package de nuestro módulo que acabamos de crear, y vamos a añadir una línea, justo después de name, es decir:
let package = Package(
name: "StepsModule",
platforms: [.iOS(.v15), .watchOS(.v8)],
Para que quede mas claro, pego todo el fichero Package:
Ahora solo nos falta usar nuestro módulo en la app principal y en nuestra app del watch.
Usar nuestro módulo en nuestra app iOS y watchOS
Lo siguiente que vamos hacer es borrar nuestro ViewModel de la app. Ya que ahora usaremos el código de nuestro ViewModel que tenemos en el módulo. Al borrar el ViewModel si intentamos compilar obtendremos un error:
Al borrar el ViewModel, no sabe de donde coger esa referencia. Para arreglarlo vamos a importar nuestro módulo en ContentView.
Antes de compilar, vamos a añadir nuestro módulo en la sección de Frameworks, Libraries, and Embedded Content
Y si compilamos nuestra app, vemos que funciona perfectamente:
Ahora, vamos a hacer exactamente lo mismo para nuestra extensión del Apple Watch, vamos a:
- Importar nuestro módulo en la sección de Frameworks, Libraries, and Embedded Content
- Añadir en Signing & Capabilities HealthKit
- Añadir la Key Privacy - Health Share Usage Description con el valor Hola! queremos acceder al número de pasos que has realizado a lo largo de hoy en los targets de nuestro Apple Watch.
Una vez hecho esto, podemos copiar y pegar la vista ContentView de nuestra app en la ContentView de nuestra WatchKit Extension:
Y vamos a compilar a ver qué ocurre:
Acaba de funcionar perfectamente. Acabamos de crear una app que funciona en un iPhone y en un Apple Watch. Pero para dejarlo de 10, vamos a mover la vista que hemos duplicado en el Apple Watch y la vamos a meter dentro de nuestro módulo:
Ahora en las vistas ContentView de nuestra app y nuestro WatchKit Extension, podemos actualizarlo a:
Ahora sí ¡Mucho más limpio!
Conclusión
Hoy hemos aprendido a cómo crear una app que funciona igual en un iPhone que en un Apple Watch. Y hemos reusado toda su lógica