Um snapshot na lista de captura não é uma cópia profunda do objeto. Um inteiro preserva o valor da criação da closure; uma referência de classe aponta para o mesmo objeto. weak é outra escolha de propriedade e não mantém o alvo vivo.
Mecanismo e decisão de projeto
Uma closure que captura uma variável local mutável pode observar mudanças posteriores. Uma lista como [number] guarda o valor inicial. Armazenar um parâmetro de closure para uso após o retorno exige @escaping, mas isso não implica assincronia ou vazamento. Fonte primária
Código reproduzível
Em uma função criamos capturas viva e de snapshot e alteramos number para 2. Capturamos uma referência antes de mudar o objeto para 3 e liberamos outro objeto capturado com weak. Queue guarda o callback, executa uma vez e o remove.
Este exemplo independente foi executado em 2026-10-23 com Apple Swift 6.4 para arm64 macOS, no modo de linguagem Swift 6. Não requer rede nem pacotes adicionais.
Baixar o arquivo Swift completo
Execute o comando na pasta do download. As precondições interrompem a execução se uma verificação falhar. Não use -Ounchecked: essa opção remove as verificações.
swift -swift-version 6 swift-closure-capture-weak-self-escaping.swift
final class Box { var value = 1 }
final class Queue {
private var action: (() -> Int)?
func enqueue(_ action: @escaping () -> Int) { self.action = action }
func run() -> Int? {
let current = action
action = nil
return current?()
}
}
func experiment() {
var number = 1
let live = { number }
let snapshot = { [number] in number }
number = 2
precondition(live() == 2 && snapshot() == 1)
let box = Box()
let capturedReference = { [box] in box.value }
box.value = 3
precondition(capturedReference() == 3)
var temporary: Box? = Box()
let weakRead = { [weak box = temporary] in box?.value }
precondition(weakRead() == 1)
temporary = nil
precondition(weakRead() == nil)
let queue = Queue()
queue.enqueue(snapshot)
precondition(queue.run() == 1 && queue.run() == nil)
print("variable=2 snapshot=1 captured-object=3 weak-after-release=nil queued=1 then=nil")
}
experiment()
Saída registrada e interpretação
variable=2 snapshot=1 captured-object=3 weak-after-release=nil queued=1 then=nil
A captura viva retorna 2; o snapshot numérico, 1; e a referência capturada observa 3. weak retorna nil após liberar o alvo. Queue retorna 1 e depois nil. Esta Queue é um exemplo de armazenamento síncrono, não um escalonador assíncrono.
Escopo e limitações
Capturar não implica necessariamente alocar no heap; o compilador pode otimizar o armazenamento. [weak self] não é obrigatório: decida se omitir o trabalho quando o proprietário desaparecer é válido. Investigue caminhos diretos e indiretos de propriedade para confirmar ciclos.
O que verificar em seguida
Documente quem possui callbacks armazenados, quando são removidos e o significado do cancelamento. Não enfraqueça referências automaticamente se a operação precisa manter o proprietário vivo. O experimento ARC demonstra como romper um ciclo real.
Fontes e verificação
- The Swift Programming Language: ClosuresSwift.org · Documentação oficial · Consultado 23 de outubro de 2026Evidência: Fonte do contrato de implementação e da explicação. A saída foi verificada separadamente com o experimento incluído aqui.

