Delegate: o que é, padrão de delegação e protocolos iOS

Autor: IT Sectr Publicado: 2026-02-17 Tempo de leitura: 9 min

Delegate é um padrão de design onde um objeto delega a execução de uma tarefa a outro objeto. No iOS, o padrão é implementado através de protocolos Swift e @protocol Objective-C. Delegação é um dos padrões fundamentais do Cocoa Touch, usado em UITableViewDelegate, UITextFieldDelegate e centenas de outras APIs da Apple. De acordo com a Apple Developer Documentation (2025), cerca de 70% das classes do sistema UIKit usam delegados para personalização de comportamento sem herança.

Principais pontos

  • Delegate — um padrão onde o objeto A delega a execução de uma tarefa ao objeto B através de um protocolo ou interface
  • Protocolo Swift define um conjunto de métodos que o delegado pode ou deve implementar
  • Referência fraca ao delegado é obrigatória para prevenir ciclos de retenção e vazamentos de memória
  • UITableViewDelegate — o exemplo mais comum de delegado no iOS com mais de 20 métodos opcionais
  • Diferença do Observer: delegado é uma relação 1:1, enquanto as notificações funcionam no princípio 1:N

O que é o padrão Delegate?

Delegate é um padrão de design comportamental que permite a um objeto delegar parte de suas responsabilidades a outro objeto. Ao contrário da herança, onde uma classe filha sobrescreve os métodos da classe pai, o delegado usa composição: o objeto proprietário mantém uma referência ao delegado e chama seus métodos em pontos específicos.

O delegado define um protocolo — um conjunto de métodos que o delegado pode implementar. Os métodos são divididos em obrigatórios (required) e opcionais (optional). No Swift, os métodos opcionais do protocolo são marcados com a palavra-chave @objc optional.

Como o delegado funciona

O objeto A (proprietário) contém uma propriedade delegate — uma referência fraca ao objeto B (delegado). Quando um evento ocorre, A verifica se B implementa o método correspondente do protocolo e o chama. A referência fraca é obrigatória: sem ela, o delegado não pode ser liberado da memória porque o proprietário o mantém com uma referência forte.

Swift
protocol LoaderDelegate: AnyObject {
    func loaderDidStart(_ loader: DataLoader)
    func loader(_ loader: DataLoader, didLoad data: Data)
    func loader(_ loader: DataLoader, didFailWith error: Error)
}

class DataLoader {
    weak var delegate: LoaderDelegate?
    
    func start() {
        delegate?.loaderDidStart(self)
        // carregamento assíncrono
    }
}

A classe DataLoader define o protocolo LoaderDelegate e chama os métodos do delegado em pontos-chave do ciclo de carregamento. AnyObject garante que o protocolo só pode ser implementado por classes — isso é necessário para a referência fraca.

Como o Delegate funciona no Swift?

A implementação do delegado no Swift inclui três etapas: declarar o protocolo, criar uma propriedade delegate fraca no proprietário e implementar o protocolo na classe delegada. Vamos ver um exemplo de um UITextField personalizado com validação.

Swift
protocol ValidatorDelegate: AnyObject {
    func validate(_ input: String) -> Bool
    func validatorDidFail(_ input: String)
}

class ValidatedTextField: UITextField {
    weak var validator: ValidatorDelegate?
    
    override func textDidChange() {
        guard let text = self.text else { return }
        if validator?.validate(text) == false {
            validator?.validatorDidFail(text)
            self.layer.borderColor = UIColor.red.cgColor
        }
    }
}

class LoginViewController: UIViewController, ValidatorDelegate {
    let textField = ValidatedTextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.validator = self
    }
    
    func validate(_ input: String) -> Bool {
        return input.count >= 6
    }
    
    func validatorDidFail(_ input: String) {
        print("Validação falhou: entrada muito curta")
    }
}

LoginViewController implementa o protocolo ValidatorDelegate e se define como delegado do textField. A cada alteração de texto, ValidatedTextField chama validate(_:), e se a validação falhar — validatorDidFail(_:). O controlador atua como intermediário entre a View e a lógica de validação.

Delegate vs NotificationCenter vs Closure

A escolha entre delegado, notificações e closures depende do número de destinatários e do acoplamento dos componentes. Cada mecanismo resolve o problema de comunicação entre objetos, mas com diferentes trade-offs.

CaracterísticaDelegateNotificationCenterClosure
Tipo de comunicação1:11:N1:1
AcoplamentoFraco (através de protocolo)Muito fraco (chave de string)Médio (captura de contexto)
Segurança de tiposCompletaNenhuma (Any?)Completa
Risco de ciclo de retençãoNão (weak)NãoSim (captura de self)
Quando usarCallbacks complexos com múltiplos métodosEventos que interessam a muitosClosures simples com 1-2 callbacks

Delegate é ideal quando você precisa passar uma série de eventos relacionados a um único destinatário. NotificationCenter é melhor para notificações de broadcast. Closure é para operações assíncronas simples, como completion handlers no URLSession.

Implementação do Delegate em Objective-C

Objective-C usa @protocol e @optional para declarar delegados. Ao contrário do Swift, todos os métodos do protocolo são opcionais por padrão. A principal diferença é a chamada respondsToSelector: antes de enviar uma mensagem ao delegado, pois o método pode não estar implementado.

Objective-C
@protocol ImageCacheDelegate 
@optional
- (void)cacheDidStartDownload: (ImageCache *)cache;
- (void)cache: (ImageCache *)cache didCacheImage: (UIImage *)image;
@required
- (void)cache: (ImageCache *)cache didFailWithError: (NSError *)error;
@end

@interface ImageCache : NSObject
@property (nonatomic, weak) id<ImageCacheDelegate> delegate;
- (void)downloadImageAtURL: (NSURL *)url;
@end

@implementation ImageCache
- (void)downloadImageAtURL: (NSURL *)url {
    if ([self.delegate respondsToSelector:@selector(cacheDidStartDownload:)]) {
        [self.delegate cacheDidStartDownload:self];
    }
    // carregamento assíncrono de imagem
}
@end

A principal diferença no Objective-C: antes de chamar um método opcional, é necessária uma verificação respondsToSelector:. No Swift, os métodos opcionais do protocolo eliminam essa verificação — o optional chaining (?.) lida automaticamente com a ausência de implementação.

Erros comuns ao trabalhar com delegados

Erros no uso de delegados levam a vazamentos de memória, travamentos do aplicativo e bugs não óbvios. Vamos ver os cinco problemas mais comuns.

Referência forte ao delegado

Ciclo de retenção é o erro mais comum. Se a propriedade delegate for declarada como strong, e o delegado por sua vez possuir o objeto proprietário, um ciclo de retenção é formado. Ambos os objetos nunca serão liberados da memória. Solução: sempre declare o delegado como weak var no Swift ou @property (weak) no Objective-C.

Delegado não anulado após dealloc

Se o objeto proprietário sobreviver ao delegado e a referência permanecer, chamar o método do delegado resultará em EXC_BAD_ACCESS. A referência fraca resolve esse problema automaticamente: após o delegado ser liberado, a propriedade se torna nil. No entanto, em cenários multithread, você deve verificar adicionalmente o delegado na thread principal.

Número excessivo de métodos no protocolo

Um protocolo com mais de 20 métodos viola o Princípio de Segregação de Interfaces (ISP). UITableViewDelegate contém cerca de 30 métodos opcionais — esta é uma exceção histórica. Em seus próprios protocolos, é melhor dividir a responsabilidade em vários protocolos menores, cada um com seu próprio papel.

Exemplos de Delegate nas APIs do sistema iOS

As APIs do sistema Apple usam ativamente o padrão Delegate. Vamos ver três exemplos-chave do UIKit que aparecem em todo aplicativo iOS.

APIProtocoloMétodos-chave
UITableViewUITableViewDelegatedidSelectRowAt, heightForRowAt, willDisplay
UITextFieldUITextFieldDelegateshouldChangeCharactersIn, didBeginEditing, shouldReturn
URLSessionURLSessionDelegatedidReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError

Cada um desses protocolos implementa diferentes aspectos do comportamento: UITableViewDelegate gerencia a aparência e a resposta ao toque, UITextFieldDelegate controla a entrada de texto, URLSessionDelegate lida com eventos de rede. Isso demonstra a flexibilidade do padrão: o delegado pode ser adaptado a qualquer área de responsabilidade.

Perguntas frequentes

Qual a diferença entre delegate e dataSource no iOS?

Delegate gerencia o comportamento e a aparência (altura da célula, resposta ao toque). DataSource fornece dados (número de linhas, conteúdo das células). No UITableViewDelegate e UITableViewDataSource — são dois protocolos separados que dividem a responsabilidade entre apresentação e dados.

Por que delegate é declarado como weak?

A referência fraca previne ciclos de retenção. O proprietário (por exemplo, UITableView) mantém uma referência ao delegado apenas como weak. Se o delegado (UIViewController) possuir a tabela, uma referência forte ao delegado criaria um ciclo: ViewController → UITableView → Delegate (ViewController). Weak quebra esse ciclo.

Pode-se usar delegate no SwiftUI?

No SwiftUI, o padrão Delegate é usado com menos frequência — é substituído por @Binding, @State e closures. No entanto, o delegado ainda é usado para integração com UIKit através de UIViewRepresentable. Por exemplo, MKMapViewDelegate e WKUIDelegate continuam relevantes ao encapsular componentes UIKit no SwiftUI.

O que é @objc optional nos protocolos Swift?

@objc optional permite declarar métodos opcionais em um protocolo Swift. Este é um mecanismo de compatibilidade com o runtime do Objective-C. Sem @objc, todos os métodos do protocolo Swift são obrigatórios por padrão. Optional é usado em protocolos UIKit onde o delegado pode implementar apenas os métodos que precisa.

Quantos delegados um objeto pode ter?

Um objeto pode ter apenas um delegado para cada propriedade delegate. Se você precisar notificar vários objetos, use multicast delegate, um array de delegados ou NotificationCenter. O padrão Delegate foi originalmente projetado como uma relação 1:1.

Resumo

  • Delegate — um padrão de design comportamental que transfere a execução de uma tarefa de um objeto para outro através de um protocolo
  • Protocolo Swift declara um conjunto de métodos; métodos opcionais são marcados com @objc optional, métodos obrigatórios são sempre implementados
  • Referência fraca ao delegado é obrigatória para prevenir ciclos de retenção e vazamentos de memória
  • UITableViewDelegate é o exemplo mais conhecido; seus métodos gerenciam altura, seleção e exibição das células
  • Delegate difere do NotificationCenter por uma relação 1:1 versus 1:N e segurança completa de tipos
  • Objective-C requer a verificação respondsToSelector: para métodos opcionais, o Swift lida com isso automaticamente
  • Recomendação: use delegate para callbacks complexos com múltiplos métodos relacionados e closure para closures simples

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também