Design de software

Delegate vs Observer em Swift: comparação completa para saber quando usar cada um

No desenvolvimento para iOS, você encontra o padrão Delegate o tempo todo.

4 min de leitura
Imagem de capa de Delegate vs Observer em Swift: comparação completa para saber quando usar cada um

No desenvolvimento para iOS, você encontra o padrão Delegate o tempo todo.

Sempre que trabalha com UITableView ou UITextField, você adiciona um delegate e talvez pense: “Por que um delegate? Não dá para usar apenas uma closure ou notificação?”

Depois de aprender o padrão Observer, é fácil ficar ainda mais confuso. Ambos avisam quando algo acontece, mas qual é exatamente a diferença?

Vamos começar pela conclusão.

Delegate é uma comunicação 1:1 em que um objeto delega algo a um único destinatário: “Vou deixar isso com você”.

Observer é uma transmissão 1:N, na qual várias pessoas assinam um único evento simultaneamente.

Entendendo essa frase, você já compreendeu metade. Hoje vamos esclarecer a diferença com código.


O que é o padrão Delegate?

Delegate significa “delegação”.

Você passa uma tarefa difícil de tratar diretamente para um objeto confiável: “Decida isso por mim”.

Uma analogia do dia a dia ajuda a entender.

Quero reservar um restaurante, mas não estou com vontade de ligar, então peço a um assistente: “Faça a reserva para mim”.

Esse assistente é o delegate. Uma pessoa pede e outra recebe o pedido. Exatamente 1:1.

No Swift, essa relação é definida por um protocolo.

// Definir o trabalho delegado em um protocolo
protocol OrderDelegate: AnyObject {
    func didFinishOrder(_ menu: String)
}

class Restaurant {
    weak var delegate: OrderDelegate?  // Designar apenas uma pessoa
    func order(_ menu: String) {
        delegate?.didFinishOrder(menu)  // Notificar somente essa pessoa
    }
}

O ponto importante é que delegatenão é um array, mas uma única propriedade.

Como a tarefa é delegada a uma pessoa, naturalmente há apenas uma. Essa é a razão de Delegate ser 1:1.

Ele também tem weak. Referências fortes podem criar um retain cycle e causar vazamento de memória, por isso delegates normalmente são mantidos como referências weak.


Qual é a diferença para o padrão Observer?

Observer é o “observador”.

Quando um evento acontece, uma notificação é enviada de uma vez para vários observadores.

Vamos continuar com a analogia do assistente.

Agora, transmito pelo bairro a notícia de que o restaurante abriu: “Abrimos hoje à noite!”

Pode haver dez ouvintes ou cem. Não me importa quem está ouvindo; apenas transmito a mensagem.

Isso é uma transmissão 1:N: o padrão Observer.

No iOS, NotificationCenteré o exemplo mais conhecido.

// Evento ocorre → transmitir para todos os assinantes
NotificationCenter.default.post(name: .storeOpen, object: nil)

// Objetos interessados assinam individualmente
NotificationCenter.default.addObserver(
    self, selector: #selector(handleOpen),
    name: .storeOpen, object: nil)

Quem envia não sabe quem recebe. Apenas adiciona um nome e envia.

Quem recebe também assina por conta própria, mesmo que sejam várias pessoas.

Como não precisam conhecer umas às outras, o acoplamento é baixo; a desvantagem é ser difícil rastrear quem está ouvindo a notificação.

Só entendi de verdade depois de escrever o código
Só entendi de verdade depois de escrever o código

Delegate vs Observer em um relance

Explicar apenas com palavras pode confundir, então organizei tudo em uma tabela.

A delegação 1:1 e a transmissão 1:N ficam claras em um diagrama
A delegação 1:1 e a transmissão 1:N ficam claras em um diagrama
Categoria Delegate Observer
Comunicação 1:1 (delegação para uma pessoa) 1:N (transmissão para várias)
Conhece a outra parte? Conhecem-se claramente Não precisam se conhecer
Exemplo típico UITableViewDelegate NotificationCenter
Resposta (valor retornado) Fácil de receber Difícil de receber
Acoplamento Relativamente alto Baixo
Rastreamento/depuração Fácil Relativamente difícil

O ponto principal é: “Você precisa receber uma resposta?”

Com Delegate, você pergunta “Qual deve ser a altura desta célula?” e o outro lado retorna um valor. É uma conversa de mão dupla.

Observer apenas envia e termina. Quem envia não se importa com a reação de ninguém.


Então, quando usar cada um?

Estes são os critérios que defini usando-os em projetos reais.

Quando usar Delegate

  1. Quando você precisa se comunicar com apenas um objeto
  2. Quando precisa receber um valor (por exemplo, quantidade ou altura de células)
  3. Quando a ordem e o fluxo são claros, como em transições de tela

Quando usar Observer

  1. Quando várias telas precisam reagir simultaneamente a um evento
  2. Para eventos globais do app, como mudança no estado de login ou ativação do modo escuro
  3. Quando quem envia e quem recebe não precisam se conhecer

Por exemplo, se a tela inicial, a página de perfil e o banner superior precisam mudar após o login, Delegate não dá conta.

Como a delegação aceita apenas um destinatário, conectar os três deixa o código confuso.

Nesse caso, é muito mais limpo transmitir uma vez “Você fez login!” usando Observer.

Por outro lado, uma situação 1:1 como “O botão de confirmação do campo de entrada foi pressionado” pede um delegate ou uma closure.

Desenhar setas em um quadro branco torna tudo muito mais fácil
Desenhar setas em um quadro branco torna tudo muito mais fácil

Resumo

Mesmo parecendo semelhantes, basta pensar “quantas pessoas precisam ser notificadas?” para escolher.

Uma pessoa: Delegate; várias pessoas: Observer. Só essa regra já é suficiente.

Tente aplicar o que aprendeu na próxima vez que escrever código. Quando o que você conhecia apenas na teoria se torna natural na prática, os padrões ficam muito mais fáceis. Torço por você!

Continue lendo