.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 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.
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.
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.
.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.
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.
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).
.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.
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ário | onAppear | onDisappear |
|---|---|---|
| Push | Nova tela | Não (tela permanece na pilha) |
| Pop | Tela que retorna | Tela que está sendo deixada |
| Troca de aba | Nova aba | Aba antiga |
| Fechar sheet | Tela pai | Sheet aberto |
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.
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.
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.
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.
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.
.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 iOS | iOS 13+ | iOS 15+ |
| Suporte async | Apenas via Task {} | Async/await nativo |
| Autocancelamento | Não | Ao desaparecer a View |
| Rechamada | A cada aparição | Uma vez por padrão |
| Código síncrono | Sim | Apenas 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.
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.
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.
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
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.
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.
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.
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.
.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
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.
Leia também