45
DELEGATES Desvendando esse poderoso padrão na API do iOS

iOS Delegates - Mobile Conf Rio 2014

  • Upload
    osnipso

  • View
    389

  • Download
    4

Embed Size (px)

DESCRIPTION

Presented at Mobile Conf Rio 2014, Brazil. The content is in Brazilian Portuguese. Discussion of the Delegate pattern and its implementation in iOS API. Samples from the SDK and a custom interaction using delegates. Shows techniques such as performSelector: calls, delegation through protocol and delegation using blocks. Code samples: https://github.com/osnipso/mobileconf2014 Caelum IP-67 course on iOS (in Brazilian Portuguese): http://www.caelum.com.br/curso-ios-iphone-ipad/

Citation preview

Page 1: iOS Delegates - Mobile Conf Rio 2014

DELEGATESDesvendando esse poderoso padrão

na API do iOS

Page 2: iOS Delegates - Mobile Conf Rio 2014

APRESENTAÇÃO

Osni Oliveira

[email protected]

@osnipso

github.com/osnipso

Page 3: iOS Delegates - Mobile Conf Rio 2014

CONHECIMENTO

• Básico de Objective-C

• Conceitos fundamentais do iOS

• Views

• Actions

•Outlets

slideshare.net/osnipso/primeiros-passos-no-ios-com-objectivec

Page 4: iOS Delegates - Mobile Conf Rio 2014

DELEGATES

• Padrão de Projeto (Design Pattern)

•Divisão de responsabilidades

• Princípio da responsabilidade única

• Comunicação entre objetos

• Inversão de Controle (IoC)

Page 5: iOS Delegates - Mobile Conf Rio 2014

DELEGATES

Colaboração entre objetos

Page 6: iOS Delegates - Mobile Conf Rio 2014

IMPORTÂNCIA

• É *o* padrão mais importante no iOS

•Muito utilizado pela API

•Muito utilizado pelos desenvolvedores

• Imprescindível compreender

•Necessário dominar

• Boa prática utilizar - padronização

Page 7: iOS Delegates - Mobile Conf Rio 2014

DEFINIÇÕES

•Delegation (iOS Developer Library - Cocoa Core Competencies)

https://developer.apple.com/library/ios/documentation/general/conceptual/DevPedia-CocoaCore/Delegation.html

•Delegates and Data Sources (iOS Developer Library - Concepts in Objective-C Programming)

https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html#//apple_ref/doc/uid/TP40010810-CH11

Page 8: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

Apple (Cocoa Core Competencies):

Delegação é um padrão simples e poderoso em que um objeto em um programa age no lugar de, ou em coordenação com outro objeto.

(...)

O objeto que delega é tipicamente um objeto do framework e o delegado é tipicamente um objeto controller customizado.

Page 9: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

Delega(framework) Delegado

MensagemProtocolo (opcional)

Page 10: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

• Recebe o delegado como dependência (injeção)

• Faz a “primeira parte” da tarefa

• Envia a mensagem

Delega(framework)

Page 11: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

• É injetado para o objeto que delega

• Garante a implementação da mensagem

• Faz a “segunda parte” da tarefa

Delegado

Page 12: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

•Opcional

• Contrato formal

• Acoplamento através do contrato (leve)

Protocolo

Page 13: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

Dois objetos colaboram para realizar uma tarefa.

O primeiro, faz até onde ele consegue fazer.

O que ele não consegue? Delega para o segundo!

Page 14: iOS Delegates - Mobile Conf Rio 2014

CONCEITO

Delega(framework) Delegado

MensagemProtocolo (opcional)

Page 15: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO: UIAlertView

(ViewController.h)

@interface ViewController : UIViewController <UIAlertViewDelegate>

(ViewController.m)

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Exemplo 1" message:@"Começando com delegates" delegate:self cancelButtonTitle:@"Cancela" otherButtonTitles:@"Ok", nil];

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { ... }

Page 16: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO: UIAlertView

UIAlertView ViewController

alertView:clickedButtonAtIndex:

UIAlertViewDelegate

delegatereferência

Page 17: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO: UIAlertView

• Sabe exibir a mensagem e os botões

• Sabe qual botão foi tocado (“clicado”) pelo usuário

•Não sabe o que fazer a partir desse ponto!

•Depende da aplicação

• Aciona o delegado para fazer

Page 18: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO: UIImagePickerController

(ViewController.h)

@interface ViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

(ViewController.m)

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;imagePicker.delegate = self; [self presentViewController:imagePicker animated:YES completion:nil];

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { ... }

Page 19: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO: UIImagePickerController

UIImagePickerController ViewController

imagePickerController:didFinishPickingMediaWithInfo:

UINavigationControllerDelegate (*)UIImagePickerControllerDelegate

delegatereferência

Page 20: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO: UIImagePickerController

• Sabe exibir a galeria de imagens/vídeos (câmera, etc.)

• Sabe qual image/vídeo foi selecionado pelo usuário

•Não sabe o que fazer a partir desse ponto!

•Depende da aplicação

• Aciona o delegado para fazer

Page 21: iOS Delegates - Mobile Conf Rio 2014

OUTROS EXEMPLOS

• UITableView

• UITableViewDelegate (interação com UI / exibição avançada)

• UITableViewDataSource (exibição básica)

Page 22: iOS Delegates - Mobile Conf Rio 2014

OUTROS EXEMPLOS

• UIApplicationDelegate

(AppDelegate.h)

@interface AppDelegate : UIResponder <UIApplicationDelegate>

Page 23: iOS Delegates - Mobile Conf Rio 2014

E O CONTRATO?

• Acoplamento a um protocolo específico

•Melhor que acoplar diretamente à classe...

•Obrigatoriedade de implementar todas as mensagens (?)

• Péssimo. Implementações vazias, adapters, etc.

Page 24: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

• UIPickerController, porém seleciona ao confirmar

• Permite cancelar seleção

• Exibido como modal

Page 25: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

• MYPickerViewController é quem implementa UIPickerViewDataSource, UIPickerViewDelegate

(MYPickerViewController.h)

@interface MYPickerViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>

• Exibe conteúdo fixo

• Seguindo a mesma idéia, podemos perguntar a um DataSource o que exibir... (desafio)

Page 26: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

• Precisamos usar performSelector:

•Delegate pode ser genérico, mas precisa implementar o protocolo NSObject

(MYPickerViewController.h)

@property (weak, atomic) id<NSObject> delegate;

(MYPickerViewController.m)

if ([self.delegate respondsToSelector:@selector(pickedItem:)]) { [self.delegate performSelector:@selector(pickedItem:) withObject:@(self.selectedItem)];}

Page 27: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

• Problemas com o compilador:

• Até dá pra desligar esse aviso, mas...

Page 28: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

MYPickerViewController ViewController

cancelPicking (opcional)pickedItem: (opcional)

NSObject

delegatereferência

Page 29: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

Prós:

•Menos trabalho

• Sem implementações desnecessárias, adapters

Contras:

• Contrato implícito!

• Sem autocomplete

• Sem ajuda do compilador

•Muito limitado!

Page 30: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - SEM PROTOCOLO

Limitações

• Protocolo NSObject

performSelector:

performSelector:withObject:

performSelector:withObject:withObject:

• Boxing (syntax sugar)

Page 31: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM PROTOCOLO

(MYPickerViewController.h)

@class MYPickerViewController;

@protocol MYPickerViewControllerDelegate <NSObject>

@optional- (void)cancelPickerViewController: (MYPickerViewController *)pickerViewController;

@required- (void)pickerViewController:(MYPickerViewController *)pickerViewController pickedItem:(NSInteger)itemIndex;

@end

@property (weak, atomic) id<MYPickerViewControllerDelegate> delegate;

Page 32: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM PROTOCOLO

(MYPickerViewController.m)

- (IBAction)cancelPicking:(id)sender{ if ([self.delegate respondsToSelector: @selector(cancelPickerViewController:)]) { [self.delegate cancelPickerViewController:self]; }}

- (IBAction)confirmPicking:(id)sender{ [self.delegate pickerViewController:self pickedItem:self.selectedItem];}

Page 33: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM PROTOCOLO

MYPickerViewController ViewController

cancelPickerViewController: (opcional)pickerViewController:pickedItem:

MYPickerViewControllerDelegate

delegatereferência

Page 34: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM PROTOCOLO

Prós:

• Contrato explícito

• Com autocomplete

• Com ajuda do compilador

•Mais flexível e poderoso

Contras:

•Mais trabalho

Com @optional:

• Sem implementações desnecessárias, adapters

• Continua autocomplete!

Page 35: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

(MYPickerViewController.h)

@property (copy, atomic) void (^cancelBlock) (MYPickerViewController *pickerViewController);

@property (copy, atomic) void (^successBlock) (MYPickerViewController *pickerViewController, NSInteger itemIndex);

Page 36: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

(MYPickerViewController.m)

- (IBAction)cancelPicking:(id)sender{ if (self.cancelBlock) { self.cancelBlock(self); }}

- (IBAction)confirmPicking:(id)sender{ if (self.successBlock) { self.successBlock(self, self.selectedItem); }}

Page 37: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

(ViewController.m)

MYPickerViewController *pickerViewController = [[MYPickerViewController alloc] init]; pickerViewController.cancelBlock = ^(MYPickerViewController *pickerViewController) { [self dismissViewControllerAnimated:YES completion:nil]; }; pickerViewController.successBlock = ^(MYPickerViewController *pickerViewController, NSInteger itemIndex) { NSLog(@"Item selecionado: %ld", (unsigned long)itemIndex);

[self dismissViewControllerAnimated:YES completion:nil]; };

[self presentViewController:pickerViewController animated:YES completion:nil];

Page 38: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

MYPickerViewController ViewController

void (^cancelBlock)(MYPickerViewController *pickerViewController);void (^successBlock)(MYPickerViewController *pickerViewController, NSInteger itemIndex);

Contrato está na assinatura do bloco!

blocobloco (cópia)

Page 39: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

Prós:

• Contrato explícito

• Com ajuda do compilador

• (Ainda) mais flexível e poderoso

Contras:

• Uma propriedade por callback

• Sintaxe bizarra!

• Problemas de gerenciamento de memória...

Page 40: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

•Dá pra melhorar um pouquinho a sintaxe...

(MYPickerViewController.h)

typedef void (^MYPickerViewControllerCancelBlock) (MYPickerViewController *pickerViewController);

typedef void (^MYPickerViewControllerSuccessBlock) (MYPickerViewController *pickerViewController, NSInteger itemIndex);

@property (copy, atomic) MYPickerViewControllerCancelBlock cancelBlock;@property (copy, atomic) MYPickerViewControllerSuccessBlock successBlock;

Page 41: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

• Cuidado com ciclos de retenção!

MYPickerViewController ViewController

blocobloco (cópia de self - “strong”)

picker

pickerViewController (strong)

Page 42: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

Cuidado:

• Fechamento (closure) no escopo da instância

• Programação funcional - paradigma misto

• Extensão da linguagem C, ainda não padronizada

Curiosidade:

• Sintaxe é a mesma de ponteiro de função (“*” vira “^”)

Page 43: iOS Delegates - Mobile Conf Rio 2014

EXEMPLO - COM BLOCOS

• Resolvendo (possíveis) ciclos de retenção:

(ViewController.m)

typeof(self) __weak weakSelf = self;

pickerViewController.cancelBlock = ^(MYPickerViewController *pickerViewController) { [weakSelf dismissViewControllerAnimated:YES completion:nil]; }; pickerViewController.successBlock = ^(MYPickerViewController *pickerViewController, NSInteger itemIndex) { NSLog(@"Item selecionado: %ld", (unsigned long)itemIndex);

[weakSelf dismissViewControllerAnimated:YES completion:nil]; };

Page 44: iOS Delegates - Mobile Conf Rio 2014

DICAS

• Procure entender o conceito (callback...?)

•Observe as APIs e como elas utilizam o padrão

•Na dúvida, implemente com protocolos (tradicional)

• APIs novas usam cada vez mais blocos - tendência

Page 45: iOS Delegates - Mobile Conf Rio 2014

OBRIGADO!

slideshare.net/osnipso/ios-delegates-mobile-conf-rio-2014

github.com/osnipso/mobileconf2014

[email protected]

@osnipso