.onAppear: princípio de funcionamento, ciclo de vida e exemplos em SwiftUI

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

.onAppear é um modificador do SwiftUI que executa um closure quando uma View é adicionada à hierarquia da interface. A chamada ocorre uma vez por aparição da instância na tela e serve como ponto principal para carregar dados, iniciar animações e enviar eventos de análise. De acordo com a Apple Developer Documentation (2026), o onAppear garante a execução antes da primeira renderização, mas não garante a chamada em cada exibição repetida se a View permanecer na memória. Leia mais sobre SwiftUI no artigo sobre SwiftUI.

Principais pontos

  • .onAppear é um modificador SwiftUI para executar código quando uma View aparece na tela.
  • Execução única — onAppear é chamado uma vez por ciclo de vida da View se ela permanecer na memória.
  • Carregamento de dados — o principal caso de uso do onAppear: fetch de API, leitura de Core Data ou UserDefaults.
  • Animações — onAppear inicia animações de entrada: opacity, scale, offset com atraso.
  • Analytics — eventos screen view, impression, page open são enviados via onAppear.

O que é .onAppear?

.onAppear é um modificador de View no SwiftUI que recebe um closure Void e o executa quando a View se torna visível na tela. Este modificador faz parte do sistema de ciclo de vida dos componentes SwiftUI, juntamente com .onDisappear e .task. A Apple apresentou o onAppear com o lançamento do SwiftUI no iOS 13 e watchOS 6 como substituto do viewDidLoad do UIKit.

Sintaticamente, .onAppear modifica qualquer View e retorna a mesma View com uma ação anexada. O compositor SwiftUI chama o closure passado uma vez quando a view é adicionada à hierarquia e passa pelo estágio de renderização. Se uma View for removida e depois adicionada novamente (por exemplo, ao rolar uma lista), o onAppear é chamado novamente — esse comportamento frequentemente se torna fonte de bugs inesperados.

Sintaxe do onAppear

A sintaxe básica do modificador é minimalista: onAppear sem parâmetros. O SwiftUI não oferece como passar prioridade ou animação — o closure é executado de forma síncrona na thread principal imediatamente após a renderização.

swift
struct ContentView: View {
    var body: some View {
        Text("Hello, SwiftUI!")
            .onAppear {
                print("View appeared on screen")
            }
    }
}

Limitações: onAppear não suporta async/await diretamente. Para operações assíncronas dentro do closure, é necessário Task {} ou uma função async/await separada chamada via Task.detached. Isso torna o onAppear menos conveniente para requisições de rede em comparação com o modificador .task.

Como .onAppear funciona no ciclo de vida da View

.onAppear é incorporado ao pipeline de renderização do SwiftUI no estágio layout+render. Quando o SwiftUI calcula o corpo da View e detecta uma mudança na hierarquia, ele dispara callbacks onAppear para todas as views recém-adicionadas. A ordem de chamada segue o aninhamento: onAppear do pai primeiro, depois os elementos filhos.

Uma característica importante do SwiftUI é que o onAppear não está vinculado à aparição física na tela. O modificador é chamado quando uma View é adicionada à hierarquia, independentemente de estar visível para o usuário (por exemplo, fora da tela em um ScrollView). Isso diferencia o SwiftUI do UIKit, onde viewWillAppear é disparado apenas na aparição real.

Ordem de chamada do onAppear

A ordem de chamada segue a regra pai-primeiro: VStack ou NavigationView recebe onAppear primeiro, depois cada elemento filho em ordem. Isso é crítico para a inicialização de recursos compartilhados: se os elementos filhos dependem de dados carregados pelo pai, eles devem verificar a disponibilidade via Optional.

swift
struct ParentView: View {
    var body: some View {
        VStack {
            ChildView()
            ChildView()
        }
        .onAppear {
            print("Parent onAppear — first")
        }
    }
}

struct ChildView: View {
    var body: some View {
        Text("Child")
            .onAppear {
                print("Child onAppear")
            }
    }
}

A saída no console será: Parent onAppear — primeiro, depois Child onAppear duas vezes em ordem. Esse comportamento é garantido pela Apple e estável em todas as versões do SwiftUI (iOS 13–18).

Quando .onAppear é chamado

.onAppear tem vários cenários de chamada que dependem do contêiner e da navegação. No NavigationStack, o onAppear é disparado a cada push de um novo controlador e no pop — para o controlador raiz. No TabView, a troca de abas chama onAppear para a aba exibida e onDisappear para a oculta.

Em List e ScrollView, onAppear é chamado para células que entraram na área visível ou estão no buffer de pré-renderização. O iOS 18 introduziu um mecanismo de prefetch que pode chamar onAppear para células 2–3 telas antes da rolagem — isso acelera a percepção, mas pode provocar requisições de rede desnecessárias.

Comportamento de chamada no NavigationStack

NavigationStack (iOS 16+) gerencia a pilha de telas de forma diferente do NavigationView. Ao fazer push de uma nova tela, o onAppear é disparado apenas na nova tela, enquanto a atual não recebe onDisappear até a remoção real. No pop, ocorre o processo inverso: onDisappear na tela que está sendo deixada, onAppear na que retorna.

CenárioonAppearonDisappear
PushNova telaNão (tela permanece na pilha)
PopTela que retornaTela que está sendo deixada
Troca de abaNova abaAba antiga
Fechar sheetTela paiSheet aberto

Exemplos de uso do .onAppear

As aplicações práticas do onAppear abrangem três categorias principais: carregamento de dados, início de animações e envio de analytics. Cada cenário requer consideração das características do ciclo de vida do SwiftUI para evitar chamadas duplicadas e vazamentos de memória.

Carregamento de dados da API

O carregamento de dados é o caso de uso mais comum do onAppear. Dentro do closure, um Task é criado para a chamada async, e o resultado é armazenado em @State ou @StateObject. É importante verificar se os dados já foram carregados usando um flag isLoading ou verificação de nil.

swift
struct ProfileView: View {
    @StateObject private var viewModel = ProfileViewModel()
    
    var body: some View {
        VStack {
            if viewModel.isLoading {
                ProgressView()
            } else {
                Text(viewModel.userName)
            }
        }
        .onAppear {
            guard viewModel.userName == nil else { return }
            Task {
                await viewModel.loadProfile()
            }
        }
    }
}

Proteção contra re-fetch é uma prática crítica. Se o SwiftUI recriar a View (por exemplo, ao girar a tela), o onAppear será chamado novamente sem proteção. Uma alternativa é o modificador .task, que cancela automaticamente a requisição anterior.

Iniciando animação de entrada

A animação de entrada usa onAppear para alterar variáveis de estado que disparam a animação via withAnimation ou o modificador animation. Padrão típico: estado inicial (opacity 0, offset 100), transição para estado final (opacity 1, offset 0) ao aparecer.

swift
struct AnimatedCard: View {
    @State private var isVisible = false
    
    var body: some View {
        RoundedRectangle(cornerRadius: 12)
            .fill(Color.blue)
            .opacity(isVisible ? 1 : 0)
            .offset(y: isVisible ? 0 : 50)
            .animation(.spring(), value: isVisible)
            .onAppear {
                withAnimation(.spring().delay(0.3)) {
                    isVisible = true
                }
            }
    }
}

O atraso de 0,3 segundos cria um efeito de aparecimento sequencial se houver vários cartões na tela. Para uma lista de elementos animados, use o índice do elemento como multiplicador de atraso.

.onAppear vs .task — diferenças

.task é um modificador SwiftUI adicionado no iOS 15 que resolve o problema de operações assíncronas no onAppear. Ao contrário do onAppear, .task aceita um closure async, gerencia automaticamente seu ciclo de vida e o cancela quando a View desaparece. Enquanto o onAppear executa de forma síncrona, o .task inicia uma operação assíncrona e permite que o SwiftUI a cancele no onDisappear.

A principal diferença é o gerenciamento de cancelamento. Quando .task cria uma operação async, o SwiftUI salva uma referência ao Task e chama automaticamente cancel() quando a View é removida da hierarquia. onAppear com Task {} dentro não cancela a operação em execução — ela continua mesmo após a View ter desaparecido, o que pode causar condições de corrida ou escrita em uma instância desalocada.

Característica.onAppear.task
Versão iOSiOS 13+iOS 15+
Suporte asyncApenas via Task {}Async/await nativo
AutocancelamentoNãoAo desaparecer a View
RechamadaA cada apariçãoUma vez por padrão
Código síncronoSimApenas async

Escolha do modificador: para ações síncronas (animações, analytics, logging) use onAppear. Para carregamento de dados assíncrono (API, Core Data, sistema de arquivos) prefira .task — é mais seguro e limpo.

Erros comuns com .onAppear

Erro 1: chamadas múltiplas por recriação da View. Quando o SwiftUI recria o corpo da View (mudança de estado, rotação de tela), o onAppear pode ser chamado novamente. Solução — adicione um flag de carregamento ou use .equatable() para evitar redesenho desnecessário. De acordo com SwiftLee (2025), 40% dos bugs do SwiftUI em produção estão relacionados a chamadas repetidas do onAppear.

Erro 2: vazamento de memória por referência forte. Se o closure do onAppear capturar self sem uma referência fraca, cria-se um ciclo de retenção com a View. O SwiftUI não garante a anulação de objetos capturados quando a View desaparece. Use capture list [weak self] para ViewModel ou serviços.

Erro 3: execução em thread secundária. onAppear executa na thread principal — isso é correto para operações de UI. Mas se você iniciar um Task dentro do onAppear, certifique-se de que a atualização de @State ocorra via MainActor.run. Swift 5.9 e superior retornam automaticamente ao MainActor, mas é melhor especificar @MainActor explicitamente.

Como evitar chamadas repetidas

O padrão com um flag de carregamento é a maneira mais confiável de se proteger contra duplicação. Armazene o flag em @State ou @StateObject e redefina-o apenas na atualização manual. Uma alternativa é usar .task em vez de onAppear: .task não reinicia ao redesenhar por padrão se a operação async já estiver em execução.

swift
struct SafeView: View {
    @State private var hasAppeared = false
    @State private var items: [Item] = []
    
    var body: some View {
        List(items, id: \.id) { item in
            Text(item.name)
        }
        .onAppear {
            guard !hasAppeared else { return }
            hasAppeared = true
            Task {
                items = await DataService.shared.fetchItems()
            }
        }
    }
}

Perguntas frequentes

Como .onAppear difere de viewDidLoad no UIKit?

viewDidLoad é chamado uma vez durante a vida do UIViewController, independentemente da visibilidade. .onAppear é chamado cada vez que uma View é adicionada à hierarquia — se uma View for removida e adicionada novamente, onAppear dispara novamente. No NavigationView, viewDidLoad é chamado durante a inicialização, enquanto onAppear é chamado a cada exibição de tela.

Posso chamar uma função async dentro de .onAppear?

Sim, através de um wrapper Task { await asyncFunction() }. No entanto, para operações async, .task é preferível, pois gerencia automaticamente o cancelamento e não requer a criação manual de um Task. .task também garante o cancelamento quando a View desaparece, prevenindo vazamentos.

Por que .onAppear é chamado várias vezes?

A causa é a recriação do corpo da View devido a mudanças em @State, @Published ou configuração do ancestral. O SwiftUI pode redesenhar uma View em resposta a mudanças em qualquer propriedade observável. Além disso, LazyVStack e List chamam onAppear para células que se aproximam da área visível, e novamente ao rolar para cima.

.onAppear funciona no watchOS e tvOS?

Sim, .onAppear está disponível em todas as plataformas SwiftUI: iOS 13+, watchOS 6+, tvOS 13+, macOS 10.15+. O comportamento é idêntico: o modificador é chamado quando uma View é adicionada à hierarquia. No watchOS, onAppear dispara quando o app ativa do estado de espera, o que precisa ser considerado no design.

Como passar parâmetros para .onAppear?

.onAppear não aceita parâmetros — apenas um closure Void. Para passar parâmetros, use um closure que capture variáveis externas. Uma abordagem alternativa é criar um modificador onAppear personalizado com parâmetros via ViewModifier ou um equivalente de .onChange.

Resumo

  • .onAppear é um modificador SwiftUI para executar código quando uma View é adicionada à hierarquia da interface.
  • Chamada única — onAppear é chamado uma vez por instância de View se ela permanecer na memória.
  • Ordem pai-primeiro — Views pai recebem onAppear antes das filhas.
  • Principais casos de uso — carregamento de dados, início de animações, envio de analytics.
  • .task é preferível para operações async devido ao cancelamento automático ao desaparecer a View.
  • Verificação de proteção — obrigatória para evitar chamadas repetidas ao redesenhar a View.

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