Ingens Networks  Ingens Developments  Ingens Biometrics  Ingens Hostings

Patrones de diseño en Objective-C: Observador (NSNotificationCenter)

10 julio 2012 10:08 by rafael.aguilar

xcode

Los programadores experimentados (y no tan experimentados) en Cocoa, estamos muy acostumbrados a implementar patrones de diseño en nuestros desarrollos.

 

Un patrón de diseño que nos podemos encontrar de manera habitual es el "delegado". Este lo hemos utilizado en artículos anteriores como puede ser el de "mapas offline" cuando implementábamos el protocolo delegado CLLocationManagerDelegate para poder trabajar con nuestra posición GPS.

El delegado es una opción muy buena cuando nos encontramos en el caso de que tenemos una relación de "uno a uno" entre el objeto que delega y su delegado pero ¿qué pasaría si necesitáramos que hubiera más de un objeto delegado (múltiples observadores)? pues deberíamos implementar el patrón "observador".

 

 

PATRÓN OBSERVADOR


Este define un patrón donde un objeto (o varios) se puede registrar como observador de otro. Cuando suceda un evento en concreto, el remitente (objeto emisor) envía al centro de notificaciones dicha notificación y este se encargará de notificar a los objetos que previamente se hayan dado de alta como observadores. La implementación del patrón observador en Objective-C se realiza utilizando la clase NSNotificationCenter con la que proporcionaremos un sistema de envío global. Visto así puede resultar algo lioso pero vamos a ver un ejemplo básico de cómo implementarlo.

 

 

EJEMPLO PRÁCTICO


Vamos a ver un ejemplo en el cual contaremos el número de veces que el usuario sale de nuestra aplicación a través del botón home de nuestro dispositivo.

 

Primero de todo, el objeto emisor debe estar preparado para enviar notificaciones al NSNotificationCenter cuando ocurra el evento. Para ello, añadiremos el siguiente código a nuestro AppDelegate.m:

 

// A este método no solamente se le llamará cuando pulsemos el botón home de nuestro dispositivo, 
// sino también cuando se interrumpa temporalmente nuestra app como puede ser el caso de llamadas entrantes

- (void)applicationWillResignActive:(UIApplication *)application
{
    // El parámetro NSString es el que especifica el nombre del mensaje 
    // a enviar, seguido del objeto que manda el aviso
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ButtonHomeNotification" object:self];
}

 

Ahora tendremos que registrar el observador en el centro de notificaciones y también implementar el método que mostrará el total de veces que se ha marchado el usuario de nuestra app, para ello incluiremos lo siguiente en nuestro ViewController:

 

ViewController.h


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    // Variable de instancia que contará el número de veces que el usuario sale de nuestra app
    int contador;
}

@end

 

ViewController.m


#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	
    // Especificamos el nombre de la notificación que queremos observar y opcionalmente podemos
    // indicar el objeto que deseamos contemplar.
    // Si especificamos 'nil' como parámetro de objeto, recibiremos notificaciones de todos los elementos que envia
    // dicha notificación.
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveButtonHomeNotification:) name:@"ButtonHomeNotification" object:nil];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

-(void)receiveButtonHomeNotification:(NSNotification*) notification
{
    contador++;
    NSLog(@"Valor de contador es: %i", contador);
}

@end

 

Lo ejecutamos en nuestro terminal y cada vez que presionemos el botón home nos aparecerá lo siguiente en la ventana del debugger de Xcode:

 

 

ACTUALIZACIÓN:


Como bien ha comentado David en uno de los comentarios, se me olvidó tratar el tema de eliminarnos como observadores cuando estamos siendo desasignado. ¿Porqué es tan importante? Si no lo hacemos podremos generar un error que hará que la aplicación se cierre ya que tenemos un objeto liberado pero todavía sigue referenciado en NSNotificationCenter. Para ello en nuestro ViewController.m implementaremos un método dealloc como el que muestro a continuación:

 

- (void)dealloc {
    // Eliminarnos como observador	
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    [super dealloc];
}

 

Tags: , , , , , ,

iOS

Comentarios (7) -

11/07/2012 18:31:45 #

Marcelo

Excelente y muy claro!
Gracias

Marcelo

12/07/2012 19:36:08 #

Ricardo

Personalmente no me gusta demasiado implementar este tipo de patrón, porque al final es un lio de mensajes de un lado a otro, haciendo más complicada la comprensión del código, pero a veces no hay más remedio.

Tengo que mirar KVO, que hace algo parecido pero para controlar variables, y nunca he acabado de entenderlo del todo.

En cualquier caso un artículo muy interesante Rafa Smile

Saludos

Ricardo

12/07/2012 21:20:21 #

rafael.aguilar

Ricardo,

Yo pienso que el patrón observador es uno muy potente y me ha sacado "las castañas del fuego" en más de una ocasión pero sobretodo es la fácil implementación del mismo en nuestros desarrollos. Personas con poca experiencia en cocoa podrán hacerlo de forma muy rápida gracias a NSNotificationCenter pero tienes razón en eso de hacerte "lio con los mensajes". Como todo en esta vida hay que utilizarlo con precaución y sin abusar ;).

Te adelanto que uno de los siguientes post que quiero escribir es sobre "Multiprocesamiento con hilos (NSOperation)" y KVC-KVO que los dos están relacionados.

rafael.aguilar

13/07/2012 9:18:16 #

Ricardo

Pues como siempre lo espero con ganas.

En cuanto a lo del patrón observador estoy totalmente de acuerdo contigo, pero tuve malas experiencias con los pasos de mensajes en Android al tener que continuar una app hecha por otra persona y desde ese día les he cogido manía, procuro intentar no usarlos a no ser que sea necesario, pero la verdad es que te solucionan una papeleta muy seria sin apenas esfuerzo.

Ricardo

26/07/2012 10:31:14 #

David

Hola Rafael,

Gracias por el tutorial, conciso y claro.

Pero creo que deberías añadir también la parte de quitar el observador, para cuando ya no necesites más notificaciones y para tener un más código limpio (como liberar memoria). Me temo que mucha gente haga copy paste de tu tutorial y ni si quiera sepa que tienen que hacer el remove del observer.

Saludos David.

David

26/07/2012 11:19:54 #

rafael.aguilar

Muchas gracias David por tu aporte, no sé como se me ha podido pasar Smile

rafael.aguilar

21/11/2012 16:18:43 #

anonimo

Excelente explicacion, podrias hacer una igual ahora sobre el patron de los Delegados de una forma mas detallada

anonimo

Pingbacks and trackbacks (1)+

Agregar comentario

biuquote
  • Comentario
  • Vista previa
Loading

Archivo

Pregunta

¿Cuanto dinero gastas mensualmente en la store de tu smartphone (googleplay, appstore, marketplace,...)?





Show Results
 Ingens Networks SL en LinkedIn Ingens Networks SL en Twitter