sexta-feira, 10 de dezembro de 2010

Delegate

Minha primeira postagem é sobre a utilização de um padrão de projeto chamado "delegation", o qual é amplamente utilizado pela apple, que nos recomenda fortemente a sua utilização. Abaixo temos uma classe MyPicture que recebe em sua inicialização uma referência a um objeto chamado display do tipo UIViewController.

-(id)initInView:(UIViewController*)display{

Certo, e o que ela faz com esse display recebido? vamos com calma... primeiramente vemos que a classe de implementação "MyPicture.m" cria em sua inicialização um objeto do tipo UIImagePickerController, que é a classe da API que efetivamente desenha a janela para escolha de uma foto. Tendo o objeto armazenado na variável chamada "picker", apontamos o delegate da janela para a nossa classe que estamos criando.

showIn = display;
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;

Atenção!
1. picker.sourceType define qual a origem permitida da foto, no caso estamos recuperando a foto a partir da biblioteca de fotos.
2. picker.allowsEditing define se a foto depois de adquirida pode ser redimensionada.

Agora vem a parte mais importante, onde utilizamos efetivamente o delagete:

[showIn presentModalViewController:picker animated:YES];

Aqui apresentamos a janela, utilizando animação, mas e esse showIn? ele é o display que recebemos como parâmetro, é nesse display que a janela de busca por uma foto deverá aparecer.

Agora que a janela de escolha já está visível, temos a possíbilidade de selecionar uma foto ou cancelar, na primeira opção ao terminar de escolher uma foto a janela irá chamar o método didFinishPickingImage do seu delagate e no segundo caso irá chamar o método imagePickerControllerDidCancel. Mas repare que a nossa classe MyPicture é que é o delegate da janela, portanto são os nossos métodos que serão chamados e dentro de cada um deles, após efetuarmos as ações necessárias, devemos remover a janela de busca com:

[pickerRec.parentViewController dismissModalViewControllerAnimated:YES];

Observem que no método imagePickerControllerDidCancel nós apenas removemos a janela, mas no didFinishPickingImage nós chamamos um método updatePicture e repassamos a imagem recebida como parâmetro para o nosso delegate.

Cuidado! Repare que o delagete da classe UIImagePickerController é a nossa classe, e o delegate da nossa classe é uma outra classe que deve ser definida antes de sua utilização.

E se a classe que vai criar um objeto MyPicture e se configurar como sendo o delegate não tiver um método updatePicture para ser chamado? Ela vai ter que ter um, pois na declaração do "MyPicture.h" nós definimos que qualquer classe que queira se candidatar a ser um delegate de MyPicture, deve conter o método "updatePicture", esta configuração foi feita no seguinte trecho:

@protocol MyPictureDelegate
-(void)updatePicture:(UIImage*)image;
@end


Continua...


MyPicture.h

#import 

@protocol MyPictureDelegate

-(void)updatePicture:(UIImage*)image;

@end

@interface MyPicture : UIViewController  {
 id showIn;
 id delegate;
}
-(id)initInView:(UIViewController*)display;

@property (nonatomic, retain) id showIn;
@property (nonatomic, retain) id delegate;

@end

MyPicture.m

#import "MyPicture.h"


@implementation MyPicture

@synthesize showIn,delegate;

-(id)initInView:(UIViewController*)display{
 showIn = display;
 UIImagePickerController *picker = [[UIImagePickerController alloc]init];
 picker.delegate = self;
 picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
 picker.allowsEditing = YES;
    [showIn presentModalViewController:picker animated:YES];
 [picker release];
 return self;
}
- (void)imagePickerController:(UIImagePickerController *)pickerRec didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo{
 [pickerRec.parentViewController dismissModalViewControllerAnimated:YES];
 [delegate updatePicture:image];
}

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)pickerRec{
 [pickerRec.parentViewController dismissModalViewControllerAnimated:YES];
}

- (void)didReceiveMemoryWarning {
 // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
 
 // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
 // Release any retained subviews of the main view.
 // e.g. self.myOutlet = nil;
}


- (void)dealloc {
 printf("//my picture dealloc//");
    [super dealloc];
}


@end