.onDisappear: princípio de funcionamento e uso no SwiftUI

Autor: IT Sectr Publicado: 2026-06-26 Tempo de leitura: 10 min

.onDisappear é um modificador do SwiftUI que executa um closure quando uma View é removida da hierarquia da interface. A chamada ocorre ao fechar uma tela, alternar de aba, dispensar uma janela modal ou rolar um elemento para fora da visibilidade. De acordo com a Documentação para Desenvolvedores da Apple (2026), onDisappear não garante chamada em cenários de falha ou quando o aplicativo é encerrado pelo watchdog do sistema. Saiba mais sobre SwiftUI no artigo sobre SwiftUI.

Principais pontos

  • .onDisappear — modificador SwiftUI para executar código quando uma View desaparece.
  • Simetria — onDisappear é pareado com onAppear e é chamado em ordem inversa.
  • Limpeza de recursos — cenário principal: cancelar temporizadores, fechar conexões, salvar estado.
  • Analítica — através do onDisappear enviam-se eventos de fechamento de tela, tempo de permanência e fim de sessão.
  • Sem garantia — onDisappear não é chamado quando o aplicativo falha.

O que é .onDisappear?

.onDisappear é um modificador de View no SwiftUI que aceita um closure Void e o executa quando a View é removida da hierarquia. Junto com .onAppear, forma o ciclo de vida completo de uma tela: aparecimento — trabalho — desaparecimento. A Apple introduziu onDisappear junto com SwiftUI no iOS 13 como um análogo ao viewDidDisappear do UIKit.

Sintaticamente, .onDisappear é idêntico ao onAppear: modifica qualquer View e anexa um closure que o renderizador do SwiftUI chama quando a view é removida. Ao contrário do UIKit, onde viewDidDisappear só é acionado após a animação de transição ser concluída, onDisappear no SwiftUI pode ser chamado antes da animação terminar — no momento em que a View é marcada para remoção.

Sintaxe do onDisappear

Sintaxe básica do onDisappear é tão concisa quanto a do onAppear. O modificador não aceita parâmetros adicionais — apenas o closure, que executa sincronamente na thread principal.

swift
struct DetailView: View {
    var body: some View {
        Text("Detail Screen")
            .onDisappear {
                print("DetailView desapareceu da tela")
            }
    }
}

Como .onDisappear funciona

Mecanismo de chamada do onDisappear é o oposto do onAppear: elementos filhos recebem onDisappear primeiro, depois o pai. Esta regra child-first garante que os recursos filhos sejam liberados antes dos recursos do pai. Se um elemento filho depende de dados do pai, ele deve ser capaz de terminar corretamente sem o contexto do pai.

SwiftUI chama onDisappear quando a View é removida do grafo de renderização. Os gatilhos incluem: pop do NavigationStack, alternância de TabView, dispensa de modal (sheet/fullScreenCover) ou uma View renderizada condicionalmente (if/switch). Em List e ScrollView, onDisappear é chamado quando uma célula rola para fora do buffer de pré-carregamento.

Ordem de chamada child-first

Ordem child-first significa que se um VStack tem três View filhas, onDisappear é chamado primeiro para cada filho em ordem inversa, depois para o pai. Isso é crítico para limpeza adequada: temporizadores filhos são cancelados antes que o ViewModel pai libere recursos compartilhados.

swift
struct ParentView: View {
    var body: some View {
        VStack {
            ChildView(id: "A")
            ChildView(id: "B")
        }
        .onDisappear {
            print("Parent onDisappear — último")
        }
    }
}

struct ChildView: View {
    let id: String
    var body: some View {
        Text("Child \(id)")
            .onDisappear {
                print("Child \(id) onDisappear")
            }
    }
}

Saída do console: Child B onDisappear, Child A onDisappear, Parent onDisappear — último. A ordem inversa comparada ao onAppear garante uma cadeia de limpeza correta.

Quando .onDisappear é chamado

Cenários de chamada do onDisappear dependem do tipo de contêiner. No NavigationStack, onDisappear é acionado ao fazer pop-to-root, pop-back normal ou dispensa de tela por deslize (interactivePopGestureRecognizer). No TabView, alternar abas chama onDisappear para a aba oculta e onAppear para a mostrada — ambos modificadores são acionados quase simultaneamente.

Em Sheet e fullScreenCover, onDisappear é chamado na dispensa programática (via @Environment(\.dismiss)) ou gesto de deslize para baixo. Um detalhe importante: se um sheet foi aberto mas o usuário trocou de aplicativo, onDisappear NÃO é chamado até o fechamento real.

CenárioonDisappear é chamadoNota
Pop no NavigationStackSimImediatamente após a animação
Alternância de aba TabViewSimAba atual
Dispensa de sheetSimAntes da animação completar
Rolagem em ListSimCélula saiu da zona de pré-carregamento
Minimizar aplicativoNãoSem garantia de chamada
Falha/watchdog killNãoNão é chamado

Exemplos de .onDisappear

Principais casos de uso do onDisappear são limpeza de recursos, salvamento de estado e rastreamento. Ao contrário do onAppear, as tarefas do onDisappear executam na saída e não precisam de verificação de duplicação já que a View desaparece uma única vez.

Salvar estado e cancelar temporizadores

Salvar estado no onDisappear é especialmente útil para formulários onde os dados devem ser salvos ao sair da tela. Temporizadores e assinaturas Combine são cancelados no onDisappear para evitar vazamentos ao retornar à tela.

swift
struct FormView: View {
    @State private var draftText = ""
    @State private var timer: Timer?
    
    var body: some View {
        TextField("Enter text", text: $draftText)
            .onAppear {
                timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
                    saveDraft()
                }
            }
            .onDisappear {
                timer?.invalidate()
                timer = nil
                saveDraft()
            }
    }
    
    private func saveDraft() {
        UserDefaults.standard.set(draftText, forKey: "draft")
    }
}

Cancelamento do temporizador no onDisappear impede a execução de código após a tela já estar fechada. Sem cancelamento, o temporizador pode tentar atualizar @State que não pertence mais à View atual, causando um aviso em tempo de execução.

Rastreamento de tempo na tela

Tempo de permanência na tela é um cenário clássico de rastreamento. Registre o tempo no onAppear, calcule a diferença no onDisappear e envie um evento analítico com a duração da sessão.

swift
struct TrackedView: View {
    @State private var appearTime: Date?
    
    var body: some View {
        Text("Tracked Screen")
            .onAppear {
                appearTime = Date()
                Analytics.shared.logEvent("screen_view", params: ["screen": "TrackedView"])
            }
            .onDisappear {
                if let start = appearTime {
                    let duration = Date().timeIntervalSince(start)
                    Analytics.shared.logEvent("screen_close", params: [
                        "screen": "TrackedView",
                        "duration_ms": Int(duration * 1000)
                    ])
                }
            }
    }
}

.onDisappear vs .onAppear — diferenças

A diferença chave entre onDisappear e onAppear é a ordem de chamada e as garantias de execução. onAppear é chamado quando uma View é adicionada à hierarquia e pode ser chamado novamente na recriação. onDisappear é chamado na remoção e só é garantido de acionar em fechamento normal, não em cenários de falha.

De acordo com a WWDC 2024, a Apple recomenda tratar onDisappear como um ponto de limpeza, não como um ponto de confirmação de dados. Dados criticamente importantes (pagamentos, registros) devem ser salvos em tempo real, não no momento em que a View desaparece, já que onDisappear não é garantido quando o aplicativo é minimizado.

Característica.onAppear.onDisappear
Momento da chamadaView adicionada à hierarquiaView removida da hierarquia
OrdemParent-firstChild-first
GarantiaAltaNão em falhas
Tarefa principalInicializaçãoLimpeza
Chamada repetidaNa recriação da ViewUma vez por desaparecimento

Recomendação: use onDisappear apenas para limpeza não crítica e rastreamento. Para persistência de dados, use scenePhase ou notificações applicationWillTerminate no AppDelegate.

Cenários de uso típicos

Cenário 1: reprodução estilo YouTube. Na tela de detalhes do vídeo, onDisappear salva a posição de reprodução no UserDefaults. Ao reabrir, onAppear restaura a posição do UserDefaults, criando uma experiência de visualização contínua.

Cenário 2: cancelar assinatura Combine. Se um ViewModel usa publicadores Combine, onDisappear cancela a assinatura via cancellable?.cancel(). Isso impede atualizações da UI após sair da tela, o que é especialmente importante para listas com paginação e consultas de busca.

Cenário 3: fechar WebSocket. Em aplicativos com conexões em tempo real (mensageiros, feeds de cotações), onDisappear fecha a conexão WebSocket para economizar bateria e dados. A reconexão ocorre no onAppear ao retornar à tela.

Fechar WebSocket no onDisappear

WebSocket é um recurso típico que precisa ser fechado ao sair da tela. No exemplo abaixo, onDisappear desconecta o socket e onAppear o reconecta, proporcionando economia significativa de dados para aplicativos com várias telas.

swift
struct ChatView: View {
    @StateObject private var socket = WebSocketManager()
    
    var body: some View {
        ChatListView(messages: socket.messages)
            .onAppear {
                socket.connect()
            }
            .onDisappear {
                socket.disconnect()
            }
    }
}

Importante: ao alternar entre abas do TabView, onDisappear da aba atual e onAppear da próxima aba são acionados quase simultaneamente. Para WebSocket isso pode causar um ciclo de desconexão-reconexão que cria carga desnecessária. A solução é usar um atraso ou verificar se o socket é necessário na próxima tela.

Perguntas frequentes

.onDisappear pode não ser chamado?

Sim, .onDisappear não garante chamada em caso de falha do aplicativo (crash, watchdog kill), minimização do aplicativo sem fechar a tela ou cenários do sistema onde o aplicativo é encerrado em segundo plano. Para dados críticos, use scenePhase ou applicationWillTerminate.

Como distinguir .onDisappear de .scenePhase?

.onDisappear é acionado quando uma View é removida da hierarquia — um callback local para uma tela específica. .scenePhase (via @Environment(\.scenePhase)) é acionado quando o estado de todo o aplicativo muda: active, inactive, background. Use onAppear+onDisappear para rastreamento de tempo na tela e scenePhase para persistência de estado global.

Por que .onDisappear é chamado várias vezes seguidas?

A causa é a alternância rápida de abas ou push/pop repetido da mesma tela. O SwiftUI pode criar uma nova instância de View, remover a antiga, criar novamente — cada vez chamando onDisappear e onAppear. Verifique se você está usando .id(), .equatable() ou recriando a View no body do pai.

.onDisappear funciona no SwiftUI no macOS?

Sim, .onDisappear é totalmente suportado no macOS (10.15+) com o mesmo comportamento: é chamado ao fechar janela, remover painel de split view ou dispensar modal. No macOS, onDisappear também é chamado ao ocultar a janela (não apenas ao fechá-la), o que é importante considerar para aplicativos macOS.

Como cancelar URLSessionTask no .onDisappear?

Salve uma referência à URLSessionTask em @State e chame task.cancel() no onDisappear. Alternativamente, use o modificador .task, que cancela automaticamente a operação assíncrona quando a View desaparece. .task é preferível para todas as operações assíncronas, incluindo URLSession.

Resumo

  • .onDisappear — modificador pareado com onAppear para limpeza de recursos e rastreamento quando uma View desaparece.
  • Ordem child-first — Views filhas recebem onDisappear antes do pai para uma cadeia de limpeza correta.
  • Sem garantia de chamada — em falha, minimização ou término do sistema, onDisappear pode não ser acionado.
  • Principais casos de uso — cancelar temporizadores, fechar WebSocket, salvar estado, rastrear tempo.
  • Analítica — onDisappear envia eventos screen_close com tempo de permanência calculado via Date().timeIntervalSince.
  • Para operações assíncronas — use .task em vez de onDisappear com Task {}, pois .task cancela solicitações automaticamente.

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