Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. iOS 8

iOS 8: Crear un widget de hoy

by
Difficulty:BeginnerLength:LongLanguages:

Spanish (Español) translation by CYC (you can also view the original English article)

Una de las características nuevas más populares introducidas en iOS 8 es la capacidad de crear varios tipos de extensiones. En este tutorial, te guiaré por el proceso de creación de un widget personalizado para la sección Hoy del centro de notificaciones. Pero primero, repasemos brevemente algunos temas sobre extensiones y comprendamos los conceptos importantes que subyacen a los widgets.

1. ¿Qué es una extensión?

Una extensión es un binario de propósito especial. No es una aplicación completa, necesita una aplicación que lo contenga para ser distribuida. Esta podría ser tu aplicación actual, que puedes incluir una o más extensiones, o una recién creada. Aunque la extensión no se distribuye por separado, sí tiene su propio contenedor.

Se inicia y controla una extensión a través de su aplicación de host. Podría ser Safari, por ejemplo, si estás creando una extensión compartida, o la aplicación del sistema Hoy que se ocupa del centro de notificaciones y otros widgets. Cada área del sistema que admite la extensión se denomina punto de extensión.

Para crear una extensión, debes agregar un objetivo al proyecto de la aplicación que lo contiene. Las plantillas proporcionadas por Xcode ya incluyen los frameworks adecuados para cada punto de extensión, lo que permite que la aplicación interactúe y siga las políticas correctas de la aplicación de host.

2. Hoy - Punto de extensión

Las extensiones creadas para el punto de extensión actual, los llamados widgets, están destinados a proporcionar un acceso simple y rápido a la información. Los widgets se vinculan al framework del Centro de notificaciones. Es importante que diseñes tu widget con una interfaz de usuario simple y enfocada, porque demasiada interacción puede ser un problema. Ten en cuenta también que no tienes acceso a un teclado.

Se espera que los widgets funcionen bien y mantengan actualizado su contenido. El rendimiento es un gran punto a considerar. Tu widget debe estar listo rápidamente y usar los recursos sabiamente. Esto evitará desacelerar toda la experiencia. El sistema termina widgets que usan demasiada memoria, por ejemplo. Los widgets deben ser simples y enfocarse en el contenido que muestran.

Eso es suficiente teoría por ahora. Comencemos creando un widget personalizado de hoy. El widget que vamos a crear mostrará información sobre el uso del disco, incluida una barra de progreso para proporcionar una referencia visual rápida para el usuario. En el camino, también cubriremos otros conceptos importantes de las extensiones de iOS 8.

3. Configuración de objetivos

Paso 1: Configuración del proyecto

Si deseas construir este widget como una extensión de una aplicación existente, sigue adelante y abre tu proyecto Xcode, y ve al segundo paso. Si estás empezando desde cero al igual que yo, entonces primero necesitas crear una aplicación que lo contenga.

Abre Xcode y en el menú Archivo, selecciona Nuevo > Proyecto... Para empezar, usaremos Objective-C como el lenguaje de programación y la aplicación de Vista única.

Paso 2: Agregar nuevo objetivo

Abre el menú Archivo y elige Nuevo > Destino... En la categoría Extensión de la aplicación, selecciona la plantilla Extensión Hoy.

Notarás que el proyecto al que se agregará el objetivo es el proyecto en el que estamos trabajando actualmente y la extensión se integrará en la aplicación que lo contiene. También ten en cuenta que la extensión tiene un identificador de paquete distinto basado en el de la aplicación que contiene, com.tutsplus.Today.Used-Space.

Haz clic en Siguiente, asigna un nombre a tu widget, por ejemplo, Espacio usado, y haz clic en Finalizar para crear el nuevo objetivo. Xcode ha creado un nuevo esquema para ti y te pedirá que lo actives por ti. Haz clic en Activar para continuar.

Xcode ha creado un nuevo grupo para el widget llamado Space Used y le ha añadido varios archivos, una subclase UIViewController y un guión gráfico. Así es, un widget no es más que un controlador de vista y un guión gráfico. Si abres el encabezado del controlador de vista en el editor de código, notarás que de hecho está subclasificando UIViewController.

Si seleccionas el objetivo de extensión de la lista de objetivos, abre la pestaña Generar fases y expande la sección Enlace binario con bibliotecas, verás que el nuevo objetivo está vinculado al framework del Centro de notificaciones.

4. Interfaz de usuario

Ahora crearemos una interfaz de usuario básica para nuestro widget. Determinar el tamaño del widget es importante y hay dos maneras de decirle al sistema la cantidad de espacio que necesitamos. Uno está usando el diseño automático y el otro está usando la propiedad preferredContentSize del controlador de vista.

El concepto de diseños adaptativos también se aplica a los widgets. No solo ahora tenemos iPhones con varios anchos (y iPads y dispositivos futuros), sino que también recordamos que el widget podría necesitar mostrar su contenido en orientación horizontal. Si la interfaz de usuario se puede describir con restricciones de diseño automático, entonces esa es una clara ventaja para el desarrollador. La altura se puede ajustar más tarde con el ajuste setPreferredContentSize: si es necesario.

Paso 1: Agregar elementos

Abre MainInterface.storyboard en el editor de Xcode. Notarás que una etiqueta que muestra "Hello World" ya está presente en la vista del controlador de vista. Selecciónalo y elimínalo de la vista, ya que no lo usaremos. Agrega una nueva etiqueta a la vista y alinéala al margen derecho como se muestra a continuación.

Label inserted into view

En el Inspector de atributos, establece el color del texto en blanco, alinea el texto en el derecho y el texto de la etiqueta en 50.0%.

Label new attributes

Selecciona Tamaño para ajustar el contenido del menú Editor de Xcode para cambiar el tamaño de la etiqueta correctamente si es demasiado pequeña para ajustarse a su contenido.

A continuación, agrega una instancia de UIProgressView a la izquierda de la etiqueta y colócala como se muestra a continuación.

Progress bar inserted

Con la vista de progreso seleccionada, cambia el atributo de Tinte progresivo en el Inspector de atributos a blanco y el color de Tinte de pista a gris oscuro. Esto lo hará más visible. Esto se ve bien hasta ahora. Es hora de aplicar algunas restricciones.

Paso 2: Agregar restricciones

Selecciona la etiqueta de porcentaje y agrega una restricción superior, inferior y posterior como se muestra a continuación. Asegúrate de desmarcar la casilla de verificación Restringir a los márgenes.

Adding constraints to label

Selecciona la vista de progreso y agrega una restricción superior, principal y final. Aprovecha esta oportunidad para cambiar el espacio inicial a 3 y no olvides desmarcar Limitar a los márgenes.

Adding constraints to progress bar

Como hemos cambiado el valor de la restricción principal de la vista de progreso, tenemos un pequeño problema que debemos solucionar. El frame de la vista de progreso no refleja las restricciones de la vista de progreso. Con la vista de progreso seleccionada, haz clic en el botón Resolver problemas de diseño automático en la parte inferior y elija Actualizar frames en la sección Vistas seleccionadas. Esto actualizará el frame de la vista de progreso en función de las restricciones que establezcamos anteriormente.

Fixing the bar size

Paso 3: Compilar y ejecutar

Es hora de ver el widget en acción. Con el esquema Espacio utilizado seleccionado, selecciona Ejecutar en el menú Producto o presiona Comando-R. Revela el centro de notificaciones deslizando desde la parte superior de la pantalla hacia la parte inferior y toca el botón Editar en la parte inferior del centro de notificaciones. Tu widget debería estar disponible para agregar a la sección Hoy. Agrégalo a la sección Hoy tocando el botón Agregar a tu izquierda.

Así es como debería verse nuestra extensión.

Eso se ve bien, pero ¿por qué hay tanto espacio debajo de la vista de progreso y la etiqueta? Además, ¿por qué el sistema operativo no respetó la restricción principal de la vista de progreso?

Ambas cuestiones son los márgenes estándar establecidos por el sistema operativo. Cambiaremos esto en el siguiente paso. Sin embargo, ten en cuenta que el margen izquierdo es deseable ya que alinea la vista de progreso con el nombre del widget.

Si giras tu dispositivo o ejecutas la aplicación en un dispositivo diferente, notarás que el widget lo ajusta correctamente. Eso es gracias a Auto Layout.

Paso 4: Corregir el margen inferior

Aber TodayViewController.m en el editor de Xcode. Notarás que el controlador de vista se ajusta al protocolo NCWidgetProviding. Esto significa que debemos implementar el método widgetMarginInsetsForProposedMarginInsets: y devolver un margen personalizado devolviendo una estructura UIEdgeInsets. Actualiza la implementación del método como se muestra a continuación.

Ejecuta la aplicación nuevamente para ver el resultado. El widget debería ser más pequeño con menos margen en la parte inferior. Puedes personalizar estos márgenes para obtener el resultado que buscas.

Paso 5: Conexión de salida

Antes de continuar, terminemos la interfaz de usuario agregando dos de salida. Con el archivo del guión gráfico abierto, cambia al editor asistente y asegúrate de que muestre TodayViewController.m.

Mantén presionado Control y arrastra desde la etiqueta hasta la interfaz del controlador de vista para crear una salida para la etiqueta. Nombra la salida como percentLabel. Repite este paso y crea una salida llamada barView para la instancia de UIProgressView.

Connecting outlets

5. Visualización de datos reales

Usaremos la clase NSFileManager para calcular el espacio disponible del dispositivo. Pero, ¿cómo actualizamos el widget con esa información?

Aquí es donde entra en juego otro método del protocolo NCWidgetProviding. El sistema operativo invoca el método widgetPerformUpdateWithCompletionHandler: cuando se carga el widget y también se puede llamar en segundo plano. En este último caso, incluso si el widget no está visible, el sistema puede iniciarlo y solicitar actualizaciones para guardar una instantánea. Esta instantánea se mostrará la próxima vez que aparezca el widget, por lo general durante un corto período de tiempo hasta que se muestre el widget.

El argumento pasado en este método es un controlador de finalización al que se debe llamar cuando se actualiza el contenido o los datos. El bloque toma un parámetro de tipo NCUpdateResult para describir si tenemos contenido nuevo para mostrar. De lo contrario, el sistema operativo sabrá que no es necesario guardar una nueva instantánea.

Paso 1: Propiedades

Primero necesitamos crear algunas propiedades para mantener los tamaños libres, usados y totales. También agregaremos una propiedad para mantener el espacio utilizado en el dispositivo. Esto nos permite una mayor flexibilidad más adelante. Agrega estas propiedades a la extensión de clase en TodayViewController.m.

Paso 2: Implementando updateSizes

A continuación, crea e implementa un método auxiliar, updateSizes, para obtener los datos necesarios y calcular el espacio utilizado del dispositivo.

Paso 3: Almacenamiento en caché

Podemos aprovechar NSUserDefaults para guardar el espacio utilizado calculado entre lanzamientos. El ciclo de vida de un widget es corto, de modo que si almacenamos en caché este valor, podemos configurar la interfaz de usuario con un valor inicial y luego calcular el valor real.

Esto también es útil para determinar si necesitamos actualizar la instantánea del widget o no. Vamos a crear dos métodos de conveniencia para acceder a la base de datos predeterminada del usuario.

Ten en cuenta que usamos una macro RATE_KEY, así que no olvides agregar esta en la parte superior de TodayViewController.m.

Paso 4: Actualizando la interfaz de usuario

Como nuestro widget es un controlador de vista, el método viewDidLoad es un buen lugar para actualizar la interfaz de usuario. Hacemos uso de un método auxiliar, updateInterface para hacerlo.

Paso 5: Invocando el controlador de finalización

El número de bytes libres tiende a cambiar con bastante frecuencia. Para verificar si realmente necesitamos actualizar el widget, verificamos el espacio utilizado calculado y aplicamos un umbral de 0.01% en lugar de la cantidad exacta de bytes libres. Cambia la implementación widgetPerformUpdateWithCompletionHandler: como se muestra a continuación.

Recalculamos el espacio utilizado y, si es significativamente diferente del valor anterior, guardamos el valor y actualizamos la interfaz. Entonces le decimos al sistema operativo que algo cambió. Si no, entonces no hay necesidad de una nueva instantánea. Si bien no lo usamos en este ejemplo, también hay un valor NCUpdateResultFailed para indicar que se produjo un error.

Paso 6: Compilar y ejecutar

Ejecuta tu aplicación una vez más. Ahora debería mostrar el valor correcto de la cantidad de espacio utilizada por tu dispositivo.

6. Resumen

Repasemos el ciclo de vida de tu nuevo widget. Cuando abres el panel Hoy, el sistema puede mostrar una instantánea anterior hasta que esté listo. La vista se carga y tu widget recuperará un valor en caché en NSUserDefaults y lo usará para actualizar la interfaz de usuario.

A continuación, se llama a widgetPerformUpdateWithCompletionHandler: y recalculará el valor real. Si el valor en caché y el nuevo no son significativamente diferentes, entonces no hacemos nada. Si el nuevo valor es sustancialmente diferente, lo almacenamos en caché y actualizamos la interfaz de usuario en consecuencia.

Mientras está en segundo plano, el widget puede ser lanzado por el sistema operativo y se repite el mismo proceso. Si se devuelve NCUpdateResultNewData, se crea una nueva instantánea para mostrar para la siguiente aparición.

7. Agregar más información y animación

Aunque ya estamos mostrando el espacio utilizado, sería interesante tener un número preciso. Para evitar saturar la interfaz de usuario, haremos que nuestro widget sea más interactivo. Si el usuario toca la etiqueta de porcentaje, el widget se expande, mostrando una nueva etiqueta con números absolutos. Esta es también una gran oportunidad para aprender a usar animación en widgets.

Paso 1: Cambiar la interfaz de usuario

Abre MainInterface.storyboard y selecciona la etiqueta de porcentaje. En el Inspector de atributos, en la sección Ver, busca la opción Habilitación de la interacción del usuario y habilítala.

A continuación, debemos eliminar la restricción inferior de la etiqueta. La distancia de la etiqueta a la parte inferior de la vista cambiará de forma programática, lo que significa que la restricción se invalidará.

Selecciona la etiqueta, abre el área Tamaño en el Inspector de tamaño, selecciona la restricción de espacio inferior y presiona eliminar. También puedes seleccionar manualmente la guía de restricciones en la vista y eliminarla. La etiqueta ahora solo tiene una restricción de espacio superior y posterior como se muestra a continuación.

Updated size attributes for percent label

Selecciona el controlador de vista haciendo clic en el primero de los tres iconos en la parte superior de la escena. En el área Size de Size Inspector, configura la altura en 106.

Selecting the view controller

Agrega una nueva etiqueta a la vista y, como lo hicimos antes, establece su color en blanco en el Inspector de atributos. Además, establece el número de líneas en 3, la altura en 61 y el ancho 200. Esto debería ser suficiente para acomodar tres líneas de información. También lo quieres alineado a los márgenes inferior e izquierdo.

New label size and positioning

El último paso es abrir el editor asistente y crear una salida para la etiqueta llamada detailsLabel.

Paso 2: Configuración

El widget solo se expandirá por un breve momento. Podríamos guardar un valor booleano en NSUserDefaults y cargarlo recordando el estado anterior, pero, para mantenerlo simple, cada vez que se cargue el widget, se cerrará. Al tocar la etiqueta de porcentaje, aparece la información adicional.

Primero definamos dos macros en la parte superior de TodayViewController.m para ayudar con los tamaños.

En viewDidLoad, agrega dos líneas de código para establecer la altura inicial del widget y hacer que la etiqueta de detalles sea transparente. Nos desvaneceremos en la etiqueta de detalles cuando se toque la etiqueta de porcentaje.

Ten en cuenta que establecemos el ancho del widget en 0.0, porque el ancho será establecido por el sistema operativo.

Paso 3: Actualizar la etiqueta de detalles

En la etiqueta de detalles, mostramos los valores de espacio libre, usado y total disponible con la ayuda de NSByteCountFormatter. Agrega la siguiente implementación al controlador de vista.

Paso 4: Captura de toques

Para detectar toques, reemplazamos el método touchesBegan:withEvent: La idea es simple, siempre que se detecta un toque, el widget se expande y la etiqueta de detalles se actualiza. Ten en cuenta que el tamaño del widget se actualiza llamando a setPreferredContentSize: en el controlador view.

Paso 5: Agregar animación

A pesar de que el widget funciona con fines no estrictos, podemos mejorar la experiencia del usuario atenuando la etiqueta de detalles mientras se expande el widget. Esto es posible si implementamos viewWillTransitionToSize:withTransitionCoordinator: Se llama a este método cuando cambia la altura del widget. Debido a que se transfiere un objeto coordinador de transición, podemos incluir animaciones adicionales.

Como puedes ver, cambiamos el valor alfa de la etiqueta de detalles, pero puedes agregar cualquier tipo de animación que consideres que mejore la experiencia del usuario.

Paso 6: Compilar y ejecutar

Estamos listos para ejecutar la aplicación una vez más. Pruébalo y toca la etiqueta de porcentaje para revelar los nuevos detalles.

Conclusión

Si bien toda esta lógica puede parecer demasiado compleja para una tarea tan simple, ahora estarás familiarizado con el proceso completo para crear una extensión de hoy. Ten en cuenta estos principios al diseñar y construir tu widget. Recuerda mantenerlo simple y directo, y no olvides el rendimiento.

El almacenamiento en caché aquí no sería necesario en absoluto con estas operaciones rápidas, pero es especialmente importante si tienes un procesamiento costoso. Utiliza tu conocimiento de los controladores de vistas y comprueba que funciona para varios tamaños de pantalla. También se recomienda que evites las vistas de desplazamiento o el reconocimiento táctil complejo.

Aunque la extensión tendrá un contenedor separado, como vimos anteriormente, es posible habilitar el intercambio de datos entre la extensión y la aplicación que lo contiene. También puedes usar openURL:completionHandler: de NSExtensionContext con un esquema de URL personalizado para iniciar tu aplicación desde el widget. Y si el código es lo que necesitas compartir con tu extensión, continúa y crea un marco para usar en tu aplicación y extensión.

Espero que los conocimientos presentados aquí sean útiles al construir tu próximo gran widget de hoy.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.