Weak Reference — o que é, sintaxe e uso no desenvolvimento móvel

Autor: IT Sectr Publicado: 2026-03-30 Tempo de leitura: 9 min

Weak Reference (referência fraca) é uma referência a um objeto que não aumenta seu contador de retenção no ARC. De acordo com Apple Swift Language Guide, 2026, referências fracas são declaradas com a palavra-chave weak e são sempre opcionais. Quando o objeto é liberado, todas as referências fracas a ele são automaticamente definidas como nil, prevenindo ponteiros pendentes e tornando as referências fracas um mecanismo seguro para quebrar ciclos de retenção.

Principais pontos

  • Weak Reference — referência que não afeta o retain count do objeto; torna-se nil quando o objeto é liberado
  • Declaração — palavra-chave weak antes de var; tipo sempre opcional (?)
  • Uso — delegados, closures, relações pai-filho para quebrar ciclos de retenção
  • Segurança — definição automática para nil após a desalocação do objeto (zeroing weak)
  • Diferença do unowned — weak torna-se nil e é seguro, unowned não se torna nil e exige garantias de tempo de vida

O que é Weak Reference?

Weak Reference é uma referência não proprietária a um objeto no ARC (Automatic Reference Counting). Ao contrário de uma referência forte, que aumenta o retain count do objeto e garante seu tempo de vida, uma referência fraca permite que o objeto seja liberado mesmo se ainda estiver sendo referenciado. Após a desalocação, a referência fraca é automaticamente definida como nil — isso é chamado de zeroing weak.

Zeroing weak é uma característica chave do runtime de Swift e Objective-C. Quando o contador de referências de um objeto atinge zero e o objeto é desalocado, o runtime percorre todas as referências fracas para este objeto (armazenadas em uma tabela fraca especial) e as define como nil. Isso garante que o acesso à memória liberada (use-after-free) seja impossível através de referências fracas — qualquer leitura retorna nil.

De acordo com a Apple WWDC 2012 Session 406, as referências fracas zeroing eliminaram toda uma classe de bugs de crash relacionados a ponteiros pendentes (dangling pointers), que eram comuns no gerenciamento manual de memória (MRR). No MRR, referências fracas existiam apenas como __unsafe_unretained — elas não zeravam, e acessar um objeto desalocado resultava em EXC_BAD_ACCESS.

Sintaxe de weak em Swift e Objective-C

Vejamos a sintaxe para declarar referências fracas em ambas as linguagens do ecossistema Apple. Apesar do runtime compartilhado, a sintaxe difere, mas a semântica é idêntica.

Swift

Em Swift, referências fracas são declaradas com a palavra-chave weak antes de var. O tipo deve ser sempre opcional (Type?), pois a referência pode se tornar nil a qualquer momento. Constantes (let) não podem ser weak — apenas variáveis.

swift
class ViewController: UIViewController {
    // weak properties: only var, only optional
    weak var delegate: ViewControllerDelegate?
    weak var parentView: UIView?

    weak var completionHandler: ((Bool) -> Void)?  // ⚠️ closures não armazenam weak
    // ⬆️ Erro: weak só pode ser aplicado a tipos class, não a closures
}

Importante: weak é aplicável apenas a instâncias de classe (tipos class), AnyObject e protocolos herdados de AnyObject. Struct, enum e closures não podem ser weak — são tipos valor e não participam do ARC.

Objective-C

Em Objective-C, propriedades fracas são declaradas usando o atributo __weak ou o modificador weak em declarações de propriedade:

objective-c
// Objective-C: weak property
@interface MyViewController : UIViewController
@property (weak, nonatomic) id<MyDelegate> delegate;
@end

// Variável local fraca
__weak MyObject *weakRef = someStrongObject;

O runtime do Objective-C também fornece zeroing weak, mas adicionalmente bloqueia o uso de weak com estruturas C e alguns objetos Core Foundation. Para estes, usa-se __unsafe_unretained — sem zeroing.

Quando usar referências fracas

Referências fracas não são uma solução universal, mas uma ferramenta para cenários específicos. Usar weak em toda parte leva a complexidade desnecessária e prejudica a legibilidade. Vejamos os cenários de uso corretos.

Delegados (padrão Delegate)

Delegados — o cenário principal para weak. O objeto proprietário (por exemplo, UITableView) mantém uma referência forte a si mesmo, enquanto o delegado (UIViewController) não deve possuir a tabela. O Apple SDK garante que todos os delegates e dataSources são weak. Para seus próprios protocolos, use sempre weak var delegate.

Pai-Filho com referência reversa

Quando um objeto filho precisa referenciar seu pai (por exemplo, ChildViewController acessando um coordenador), use uma referência fraca. O pai possui o filho (strong), o filho observa o pai (weak) — o ciclo de retenção é eliminado.

Closures assíncronas

Capture list [weak self] — a maneira padrão de evitar ciclos de retenção em closures armazenadas como propriedades de classe. Se self pode ser desalocado antes da conclusão da closure, weak self é obrigatório.

CenárioWeakStrong
Delegate✅ Sempre weak❌ Retain cycle
Pai → Filho❌ Não necessário (pai deve possuir)✅ Strong
Filho → Pai✅ Weak❌ Retain cycle
Callback assíncrono✅ [weak self]❌ Risco de retain cycle
Acoplamento forte (owned)❌ unowned✅ Strong

Regra geral: se o objeto A possui B (A → B strong), então B → A deve ser weak ou unowned. A direção das referências fortes deve ser sempre do proprietário ao subordinado.

Weak vs Unowned: comparação e cenários

Tanto weak quanto unowned não aumentam o retain count, mas diferem no comportamento após a desalocação do objeto. A escolha entre eles é uma questão de garantias de tempo de vida.

Diferenças

Weak: torna-se nil automaticamente, tipo sempre opcional, requer unwrap antes do uso. Seguro — acessar nil não causa crash.

Unowned: não se torna nil, tipo não opcional. Se o objeto for desalocado, uma referência unowned se torna um ponteiro pendente — acessá-la causa um crash em tempo de execução. Unowned assume que o objeto vive pelo menos tanto quanto o lado que o referencia.

Quando escolher weak

Escolha weak se: o objeto pode ser desalocado a qualquer momento (delegado após fechar a tela), você não controla o tempo de vida do objeto, ou está inseguro sobre as garantias. Weak é a escolha segura universal.

Quando escolher unowned

Escolha unowned se: o objeto tem garantia de não ser desalocado antes do objeto que o referencia (por exemplo, Cliente → CartaoCredito, onde o cartão não existe sem o cliente). Unowned fornece uma API não opcional sem unwrap, o que é mais conveniente no código.

swift
class Order {
    let id: Int
    var items: [Item] = []

    init(id: Int) { self.id = id }

    // Relação forte: Order possui Item
    func addItem(name: String) {
        let item = Item(name: name, order: self)
        items.append(item)
    }
}

class Item {
    let name: String
    unowned let order: Order          // ✅ unowned — Item não vive sem Order

    init(name: String, order: Order) {
        self.name = name
        self.order = order
    }
}

// Exemplo com weak: delegate sem garantia de tempo de vida
protocol NetworkServiceDelegate: AnyObject {
    func didReceiveResponse(data: Data)
}

class NetworkService {
    weak var delegate: NetworkServiceDelegate?  // ✅ weak — o delegate pode desaparecer
}

No exemplo, Item usa unowned porque um item de pedido não pode existir sem o próprio pedido — a garantia de tempo de vida é inabalável. NetworkService usa weak porque o delegado (por exemplo, ViewController) pode ser fechado e desalocado a qualquer momento.

Limitações das referências fracas e armadilhas

Referências fracas são uma ferramenta poderosa, mas têm limitações que são importantes de entender para o uso correto no desenvolvimento iOS.

Desempenho de weak

Referências fracas são mais lentas que as fortes: a cada acesso, o runtime verifica se o objeto foi desalocado (lookup na tabela fraca). Na grande maioria dos cenários, a diferença é imperceptível, mas em loops críticos com milhões de acessos, weak pode se tornar um gargalo. Para cenários de alta carga, use strong e reorganize a arquitetura.

Weak não é aplicável a tipos valor

Struct, enum, tuple — tipos valor que não participam do ARC. Tentar declarar um weak struct resulta em erro de compilação. Para armazenar uma referência fraca a um tipo valor, use um wrapper em um tipo classe ou uma closure.

Weak em multithreading

Zeroing weak é thread-safe: se um objeto for desalocado em uma thread, a referência fraca é zerada em todas as threads atomicamente. No entanto, a janela entre ler uma referência fraca e desreferenciá-la pode levar a uma condição de corrida — o objeto é desalocado entre a obtenção da referência fraca e seu uso. Solução: captura forte da referência fraca em uma variável local.

swift
// Race condition com weak em multithreading
func performAsync() {
    weak var weakSelf = self
    queue.async {
        // ⚠️ weakSelf pode ser nil entre a verificação e o uso
        if weakSelf != nil {
            weakSelf!.doSomething()  // CRASH se ficar nil
        }
    }
}

// ✅ Correção: captura forte durante o uso
func performAsyncSafe() {
    queue.async { [weak self] in
        guard let strongSelf = self else { return }
        strongSelf.doSomething()  // strongSelf — referência local forte
    }
}

Na versão segura, weak self é capturado e imediatamente desembrulhado em uma variável local forte strongSelf. Se self ainda estiver vivo, permanecerá vivo durante a execução do bloco. Se não, guard é acionado e o código não é executado. Este idiom é o padrão para closures assíncronas em Swift.

UIView e weak outlets

IBOutlet no Interface Builder deve ser weak porque a hierarquia de views já mantém uma referência forte à subview. Duplicar uma referência forte no controlador não cria um ciclo de retenção, mas é redundante. Uma referência fraca a um outlet é a recomendação da Apple, embora muitos desenvolvedores usem strong para simplificar o código.

Perguntas frequentes

Uma referência fraca pode apontar para um objeto que ainda não foi criado?

Não, weak só pode apontar para um objeto existente ou nil. Ao criar um novo objeto, você primeiro obtém uma referência forte (através de um inicializador), e só então pode atribuir uma referência fraca. Um weak nil no início é um estado normal.

Por que weak funciona apenas com tipos class?

Weak é baseado no ARC, que gerencia apenas tipos referência (classes). Tipos valor (struct, enum) são copiados na atribuição e não têm retain count. Para relacionamentos fracos com tipos valor, use closures ou wrappers em uma classe com uma propriedade weak.

Como weak afeta o desempenho em um loop?

Cada acesso a uma referência fraca realiza um lookup na tabela do runtime. Em um loop com milhões de iterações, isso pode ser de 2 a 5 vezes mais lento que uma referência forte. Para caminhos críticos, copie weak para uma variável local forte antes do loop.

Quando uma referência fraca pode se tornar nil inesperadamente?

Quando todas as referências fortes ao objeto são perdidas — no final do escopo, ao reatribuir uma propriedade, ou ao fechar uma tela. Em um ambiente multithread, isso pode acontecer entre duas linhas de código. Sempre verifique referências fracas com guard let ou if let.

Como weak difere de __weak em Objective-C?

Semanticamente idênticos: ambos fornecem zeroing weak. Diferenças: Swift requer tipo opcional e var, Objective-C usa um modificador de propriedade. Objective-C também suporta __unsafe_unretained — uma referência fraca sem zeroing (risco de ponteiro pendente).

Resumo

  • Weak Reference — referência não proprietária que não aumenta o retain count e é automaticamente zerada na desalocação
  • Sintaxeweak var + tipo opcional; apenas tipos class e protocolos AnyObject
  • Zeroing weak — runtime zera todas as referências fracas a um objeto desalocado, prevenindo ponteiros pendentes
  • Cenários — delegados, pai-filho com referência reversa, closures assíncronas ([weak self])
  • Weak vs Unowned — weak torna-se nil (seguro), unowned não se torna nil (risco de crash, mas não opcional)
  • Desempenho — weak é mais lento que strong devido ao lookup na tabela do runtime; para caminhos críticos, copie para strong
  • Recomendação — se não tiver certeza sobre garantias de tempo de vida, escolha weak

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