O dilema eterno: usar [unowned self] ou não?
\n\nSe você já escreveu em Swift e se deparou com closures, certamente já se perguntou: "Preciso escrever [unowned self] dentro de cada closure onde uso self?"
Esta é uma das perguntas mais populares no Stack Overflow (dezenas de milhares de visualizações), e não é à toa. Em 2025, com o surgimento de novas funcionalidades do Swift (como o analisador de ciclo de vida aprimorado e verificações mais rigorosas do compilador), a resposta se tornou ainda mais cheia de nuances.
\n\nNeste artigo, não vamos apenas dar uma resposta seca de "sim" ou "não". Vamos analisar como o gerenciamento de memória realmente funciona no Swift, quando [unowned self] é uma salvação e quando é uma bomba-relógio, e quais melhores práticas usar em projetos modernos.
Vamos nessa! 🚀
\n\nResumo sobre ARC e retain cycles (para iniciantes)
\n\nAntes de falar sobre [unowned self], vamos lembrar como funciona o Automatic Reference Counting (ARC).
ARC é um mecanismo de contagem de referências. Cada objeto em Swift (instância de uma classe) tem um contador de referências. Quando você cria uma nova referência a um objeto (por exemplo, atribuindo-o a uma propriedade ou colocando-o em um array), o contador aumenta. Quando a referência desaparece, ele diminui. Quando o contador chega a zero, o objeto é destruído.
\n\nO problema surge quando dois objetos fazem referência um ao outro (referência cíclica). Imagine:
\n\nclass Parent {\n var child: Child?\n}\n\nclass Child {\n var parent: Parent? // Referência forte de volta para Parent\n}\n\nSe você criar um par Parent e Child e definir ambas as referências, eles se manterão mutuamente para sempre. O ARC nunca zerará seus contadores. Isso é chamado de retain cycle (ciclo de referências fortes).
Closures também são tipos por referência. Quando uma closure captura self (por exemplo, para chamar um método), ela armazena uma referência forte ao objeto. Se o objeto, por sua vez, armazena uma referência forte à closure (por exemplo, como uma propriedade), ocorre o mesmo ciclo.
Weak vs Unowned: qual a diferença?
\n\nPara quebrar o ciclo, usamos weak ou unowned.
weak self
\n- \n
- Sempre opcional (
self?). \n - A referência não aumenta o contador do ARC. \n
- Quando o objeto é destruído, a referência
weakse torna automaticamentenil. \n - Seguro — você sempre verifica com
guard let self = self else { return }. \n
unowned self
\n- \n
- Não é opcional (
selfsem o ponto de interrogação). \n - A referência não aumenta o contador do ARC. \n
- Quando o objeto é destruído, a referência
unownednão se torna nil. Ela se torna um "ponteiro solto" (dangling pointer). \n - Acessar essa referência após a destruição do objeto causa uma quebra (crash) (EXC_BAD_ACCESS). \n
Ponto-chave: unowned é uma promessa ao compilador: "Eu garanto que o objeto estará vivo enquanto esta closure estiver sendo executada". Se você errar, o aplicativo irá cair.
Quando usar [unowned self] (e quando não usar)
\n\nVamos analisar cenários reais da prática de desenvolvimento iOS em 2025.
\n\nCaso 1: [unowned self] — é ok (e até preferível)
\n\nUse [unowned self] quando você tem absoluta certeza de que self estará vivo no momento da execução da closure. Um exemplo típico é uma closure que é executada de forma síncrona dentro de um método do objeto, e o objeto tem a garantia de não ser destruído antes da conclusão da closure.
class DataFetcher {\n var data: Data?\n \n func fetchData() {\n // Esta closure é executada de forma síncrona dentro do método\n let processCl