¿Qué es un protocolo de ObjetiveC y para que se usan los protocolos en ObjetiveC?

Cuando programamos en ObjetiveC para iphone o ipad, utilizando funciones mas avanzadas de la interfaz gráfica nos encontramos con delegados, llamados también delegates. En estos casos, por ejemplo cuando tenemos un UIScrollView que captura el evento – (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView que utilizamos para controlar cuando ese UIScrollView se ha parado. Para controlar esto lo hacemos mediante el uso de los delegados. Pero mejor verlo con un ejemplo que se vea mas claro.

@implementation IndalcasaViewController

– (void)viewDidLoad {
[super viewDidLoad];
self.indalScroll.delegate = self;
}

– (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int page = scrollView.contentOffset.x / scrollView.frame.size.width;

NSLog(@»Hemos cambiado a la pagina %i», page);
}

@end

Tras este ejemplo vemos como funciona un delegado en una clase normal de ObjetiveC. Pero aún no entendemos lo que significa ser un delegado. Un delegado no es mas que un nombre de convención, que podemos llamar como queramos y que utilizaremos como disparador, donde el objeto que está almacenado implementa una serie de funcionalidades definidas en un protocolo.

Se que ahora ha quedado claro del todo :P, pero mejor verlo en un ejemplo.

@interface IndalcasaViewController : UIViewController
@end

Como vemos en el ejemplo anterior, a la hora de extender la clase UIViewController decimos que implementa el protocolo UIScrollViewDelegate. Para los mas veteranos desarrolladores, un protocolo no es mas que una interfaz. Para los mas novatos, una interfaz es como una clase donde se definen llamadas pero no se implementa código.

Para verlo todo mas sencillo, vamos a poner un último ejemplo. Lo que vamos a hacer es definir otro UIViewController al que instanciaremos en el viewDidLoad y que implementará un metodo vacío llamado «cambioPagina» que recibirá la página por parámetro.

IndalcasaViewController.h
@interface IndalcasaViewController : UIViewController

@property UIViewController delegate;
@property (weak, nonatomic) IBOutlet UIScrollView *indalScroll;

@end

IndalcasaViewController.m
@implementation IndalcasaViewController

– (void)viewDidLoad {
[super viewDidLoad];
self.indalScroll.delegate = self;
}

– (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int page = scrollView.contentOffset.x / scrollView.frame.size.width;

NSLog(@»Hemos cambiado a la pagina %i», page);

[self.delegate cambioPagina:page];
}

@end

DelegadoViewController.h
@interface DelegadoViewController : UIViewController
@end

@protocol IndalcasaDelegate

-(void)cambioPagina:(int)pagina;

@end

DelegadoViewController.m
@implementation DelegadoViewController

– (void)cambioPagina:(int)pagina {
NSLog(@»Hemos cambiado a la pagina %i con un delegado», pagina);
}

@end

Como vemos en el ejemplo, lo que hacemos es que cuando capturamos el evento scrollViewDidEndDecelerating, que nos indica que se ha parado el scroll, llamamos a un delegado, previamente seteado que implementa el protocolo (intefaz) IndalcasaDelegate. Como sabemos que el delegado, al implementar el protocolo IndalcasaDelegate tiene un método cambioPagina que recibe un entero con la página, podemos llamar al método desde el delegado.

Comentar también que en muchos casos, nos encontraremos delegados de tipo id y no de un tipo concreto. Los tipos id vendrían a ser tipos de objetos genéricos, algo parecido al object de cualquier lenguaje.