thxou

Ama la sabiduría. Desea el conocimiento.

iOS: Programando Notificaciones Locales Con UILocalNotification

| Comments

Aquí estamos otra vez con un nuevo tutorial. Esta vez intentaré explicarles de manera teórica y práctica el proceso para programar una notificación local. Es relativamente sencillo de implementar y hay pocas opciones que configurar. La clase UILocalNotification te permite representar notificaciones locales como la de la imagen (similares a las notificaciones Push que trabajan con un servidor externo, no hablaremos de esto ahora), que tu aplicación podría programar para que sean presentadas a tus usuarios en una fecha y hora determinadas. El sistema operativo es el encargado de gestionar estas notificaciones y permite programar hasta 64 notificaciones por aplicación. Esta clase adopta el protocolo NSCopying, y una de sus ventajas es que nos permite copiar notificaciones ya programadas, también modificarlas y cancelarlas. Todo en el cuadro de notificación, excepto el color, se puede personalizar al completo: puedes definir un título, el texto de la notificación, cuantos botones va a tener, un sonido personalizado el cual se reproduzca al mostrarse, etc. Todas estas opciones las vamos a aprender a configurar nosotros mismos a continuación con un ejemplo práctico.

Llevándolo a la práctica

He creado otra mini-app llamada notifyme que te puedes descargar desde el botón enorme del final de este artículo (Muy recomendado descargarla y seguir el toturial con ella). Lo que vas a aprender con esta app es a programar una notificación local con configuraciones personalizadas y recibir un texto juntamente con la notificación para mostrarla al usuario, en este caso, la mostraremos en un cuadro de texto de la pantalla principal, pero también se podría mostrar como una alerta.

Abrimos la aplicación en Xcode y en el Project Navigator podemos ver nuestro controlador de la aplicación: AppDelegate.h y .m, y también el controlador de la vista principal ViewController.h y .m. Abrimos el ViewController.m y nos vamos al método:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)programarNotificacion
{
    UILocalNotification *localNot = [[UILocalNotification alloc] init];
    localNot.fireDate = [pickerCaducidad date];
    localNot.timeZone = [NSTimeZone defaultTimeZone];

    localNot.alertBody = @"Mi primera notificación";
    localNot.alertAction = @"Mostrar";
    localNot.soundName = UILocalNotificationDefaultSoundName;
    localNot.applicationIconBadgeNumber = 1;

    NSDictionary *userDict = [NSDictionary dictionaryWithObject:textoNotificacion.text forKey:kNotificationTextKey];
    localNot.userInfo = userDict;

    [[UIApplication sharedApplication] scheduleLocalNotification:localNot];
}

Este método es la parte principal de nuestra aplicación ya que es el que va a programar la notificación, así que voy a explicarles las partes que lo componen y su configuración.

Como ya sabemos, para trabajar con clases hay que hacerlo a través de objetos, y estos objetos los creamos a través de instancias de clases, así que lo que hacemos primero es crear una instancia de la clase UILocalNotification llamada ”localNot”. Esta instancia va a representar esta notificación en la cola de notificaciones del sistema operativo. Bien, este objeto tiene las siguientes propiedades:

  • fireDate: La fecha y hora exacta en la que deseamos mostrar la notificación.
  • timeZone: Trabaja juntamente con fireDate y sirve para que la notificación se muestre adaptada para una zona horaria específica. Nosotros usamos defaultTimeZone que utiliza la zona horaria de la aplicación.
  • alertBody: Es el cuerpo del mensaje que se muestra junto con la notificación.
  • alertAction: Es el texto del botón de acción. En la imagen dice ”Mostrar” y al pulsarlo va a abrir la aplicación.
  • soundName: El sonido personalizado que quieres que se reproduzca al mostrarse la notificación. UILocalNotificationDefaultSoundName espeficica el sonido por defecto del sistema, pero podemos poner el que nosotros queramos, siempre y cuando dure 30 segundos y sean de formato aiffwav o caf.
  • applicationIconBadgeNumber: Si os habéis fijado, hay aplicaciones que muestran un circulo rojo en la parte superior derecha del icono de la app. A esto se refiere esta propiedad. Es un entero de tipo NSInteger al que podemos asignarle un número.
  • userInfo: Esta propiedad es un diccionario tipo NSDictionary, en la que podemos guardar información para luego recuperarla cuando se muestre nuestra app después de presionar el botón de acción.

Existen otras propiedades más, aparte de las usadas en esta aplicación, algunas un poco menos importantes pero que te las explico en una línea:

  • repeatInterval: Sirve para reprogramar la notificación en un intervalo de tiempo específico.
  • repeatCalendar: El calendario en el que la aplicación se basará para reprogramar la notificación.
  • hasAction: Es un propiedad de tipo BOOL, que especifica si se muestra o no el botón de acción.
  • alertLaunchImage: La imagen que se muestra inmediatamente cuando se presiona el botón de acción.

Aquí cabe explicar un poco el campo userInfo. Yo he creado una constante a la que he llamado kNotificationTextKey para usarla como el texto que quiero que acompañe a la notificación. La he declarado en el AppDelegate.h y luego asignado un string que es el nombre con el que se guardará juntamente con la aplicación. También la he declarado como extern, para que esté disponible fuera de la clase AppDelegate. Como podéis ver, el valor de esta constante es el que escribimos en el UITextField de la interfaz gráfica (textoNotificacion).

Explicado esto, es el momento de enviar la notificación (nuestro objeto ”localNot”) al sistema operativo para que la gestione. Para esto utilizamos un método de la clase UIApplication llamado scheduleLocalNotification:localNot. Este método utiliza el valor del campo fireDate para programar la notificación y que se muestre en una fecha y hora concretas. Otro método que también interesa es presentLocalNotificationNow:, el cual muestra la notificación inmediatamente por pantalla.

En este mismo archivo podemos ver el método: -(IBAction)prepararNotificacion:(id)sender. Lo que va a hacer es, a parte de ejecutar el método de arriba, cancelar todas las notificaciones programadas anteriormente utilizando el método de  UIApplication llamado cancelAllLocalNotifications. Si por el contrario, solo queremos hacerlo para una notificación específica utilizaremos cancelLocalNotification:localNot.

Mostrando la notificación

Vale, ya hemos programado  la notificación, ahora nos toca recibir y manipular la información que trae consigo la notificación cuando se muestra, así podemos personalizarla más a nuestro gusto. Hay 2 estados en los que podría encontrarse la aplicación al recibir la notificación: cuando está visible y cuando está cerrada. Como ya sabemos, al presionar en el botón de acción (o deslizar el dedo cuando el dispositivo está bloqueado) se abre la aplicación, al abrirse, dependiendo de en cual de estos 2 estados se encuentra, se ejecutan 2 métodos de UIApplication. Estos métodos los podemos encontrar ya implementados en el archivo del controlador principal de la aplicación AppDelegate.m. Si la aplicación no está visible se ejecuta el método application:didFinishLaunchingWithOptions:. El siguiente código es lo que he añadido al predeterminado para manipular los datos de la notificación:

1
2
3
4
5
6
7
8
9
10
11
    //Notificaciones
    application.applicationIconBadgeNumber = 0;
    UILocalNotification *notification = [launchOptions objectForKey:
                                         UIApplicationLaunchOptionsLocalNotificationKey];

    if (notification) {
        NSString *reminderText = [notification.userInfo
                                  objectForKey:kNotificationTextKey];
        [_viewController despliegaNotificacion:reminderText];
    }
}

Nota que el método tiene un parámetro llamado launchOptions. Este parámetro es un diccionario (NSDictionary) que lleva consigo información acerca del porque de que se haya abierto la aplicación. En este caso, cuando uno de los motivos es una notificación, esta se guarda en una constante del sistema designada para esto: UIApplicationLaunchOptionsLocalNotificationKey. Si esta constante contiene la notificación, entonces este ha sido el motivo de su apertura, así que guardamos esta notificación en un puntero que hemos llamado ”notification”. Si os acordáis, antes guardamos un texto en la constante kNotificationTextKey, por lo que ahora lo recuperamos en el string reminderText.

Si se da el otro caso, en el que la aplicación está visible entonces se ejecuta otro método de UIApplication llamado application:didReceiveLocalNotification:. No se muestran alertas ni se reproducen sonidos, pero si se puede tratar con la información que viene con la notificación:

1
2
3
4
5
6
7
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

	application.applicationIconBadgeNumber = 0;
	NSString *reminderText = [notification.userInfo
                              objectForKey:kNotificationTextKey];
    [_viewController despliegaNotificacion:reminderText];
}

Aquí hacemos similar al anterior método. Quitamos el badgeNumber y luego recuperamos el texto de la constante kNotificationTextKey en el string reminderText.

No obstante, y para finalizar, la siguiente línea:

1
    [_viewController despliegaNotificacion:reminderText];

Utiliza el objeto _viewController, creado automáticamente por Xcode al crear un nuevo proyecto, para comunicarse con el controlador de nuestra vista principal (ViewController.h y .m), cuya clase tiene implementado el método despliegaNotificacion:, todo esto con el fin de mostrarnos el texto recuperado en reminderText en la pantalla principal.

Pongan en marcha la aplicación para verla en funcionamiento. No temas cambiar el código y probar tus propias ideas. Hazlo, y si sale mal entonces aprende de tus errores. Si bien es cierto este tutorial se pudo haber hecho en menos palabras, he querido detallarlo para que puedan comprender realmente como funciona. Si me dejo algo, o digo algo en lo que me estoy equivocando, agradecería mucho vuestro feedback :). Disfruten y compartan este artículo. Hasta otra!.

Comments