.onAppear — een SwiftUI-modificator die een sluiting uitvoert bij het toevoegen van View aan de interfacehiërarchie. De aanroep vindt eenmalig plaats per verschijning van de instantie op het scherm en dient als het belangrijkste punt voor het laden van gegevens, het starten van animaties en het verzenden van analytische gebeurtenissen. Volgens Apple Developer Documentation (2026) garandeert onAppear uitvoering vóór de eerste weergave, maar garandeert geen aanroep bij elke herhaalde weergave als View in het geheugen blijft. Lees meer over SwiftUI in het materiaal over SwiftUI.
Belangrijkste punten
.onAppear — een View-modificator in SwiftUI die een Void-sluiting accepteert en deze uitvoert op het moment dat View zichtbaar wordt op het scherm. Deze modificator maakt deel uit van het levenscyclussysteem van SwiftUI-componenten naast .onDisappear en .task. Apple introduceerde onAppear samen met de release van SwiftUI in iOS 13 en watchOS 6 als vervanging voor viewDidLoad uit UIKit.
.onAppear wijzigt elke View en retourneert dezelfde View met de bijgevoegde actie. De SwiftUI-compiler roept de doorgegeven sluiting eenmaal aan wanneer de weergave aan de hiërarchie wordt toegevoegd en de renderfase doorloopt. Als View wordt verwijderd en vervolgens opnieuw toegevoegd (bijvoorbeeld bij scrollen in een lijst), wordt onAppear opnieuw aangeroepen — dit gedrag wordt vaak de bron van onverwachte bugs.
De basissyntax van de modificator is minimaal: onAppear zonder parameters. In SwiftUI is er geen mogelijkheid om prioriteit of animatie door te geven — de sluiting wordt synchroon in de hoofdthread uitgevoerd direct na het renderen.
struct ContentView: View {
var body: some View {
Text("Hallo, SwiftUI!")
.onAppear {
print("View verscheen op het scherm")
}
}
}
Beperkingen: onAppear ondersteunt async/await niet direct. Voor asynchrone bewerkingen binnen de sluiting is Task {} of een aparte async/await-functie via Task.detached nodig. Dit maakt onAppear minder handig voor netwerkverzoeken in vergelijking met de .task-modificator.
.onAppear wordt geïntegreerd in de SwiftUI-renderpijplijn in de layout+render-fase. Wanneer SwiftUI de body van View berekent en een hiërarchieverandering detecteert, start het onAppear-callbacks voor alle nieuw toegevoegde weergaven. De aanroepvolgorde komt overeen met de nestvolgorde: eerst onAppear bij de ouder, daarna bij de kindelementen.
Een belangrijk kenmerk van SwiftUI — onAppear is niet gebonden aan fysieke verschijning op het scherm. De modificator wordt aangeroepen wanneer View aan de hiërarchie wordt toegevoegd, ongeacht of deze zichtbaar is voor de gebruiker (bijvoorbeeld buiten het scherm in ScrollView). Dit onderscheidt SwiftUI van UIKit, waar viewWillAppear alleen bij daadwerkelijke verschijning werkt.
Aanroepvolgorde volgt de parent-first-regel: VStack of NavigationView ontvangt eerst onAppear, vervolgens elk kindelement op volgorde. Dit is cruciaal voor het initialiseren van gedeelde bronnen: als kindelementen afhankelijk zijn van door de ouder geladen gegevens, moeten ze de beschikbaarheid controleren via Optional.
struct ParentView: View {
var body: some View {
VStack {
ChildView()
ChildView()
}
.onAppear {
print("Parent onAppear — eerst")
}
}
}
struct ChildView: View {
var body: some View {
Text("Kind")
.onAppear {
print("Child onAppear")
}
}
}
Console-uitvoer zal zijn: Parent onAppear — eerst, daarna tweemaal Child onAppear in de volgorde van positie. Dit gedrag wordt gegarandeerd door Apple en is stabiel in alle SwiftUI-versies (iOS 13–18).
.onAppear heeft verschillende aanroepscenario's die afhankelijk zijn van de container en navigatie. In NavigationStack wordt onAppear geactiveerd bij elke push van een nieuwe controller en bij pop — voor de rootcontroller. In TabView veroorzaakt het wisselen van tabbladen onAppear voor het weergegeven tabblad en onDisappear voor het verborgen tabblad.
In List en ScrollView wordt onAppear aangeroepen voor cellen die in het zichtbare gebied zijn gekomen of zich in de pre-renderbuffer bevinden. iOS 18 introduceerde een prefetch-mechanisme dat onAppear kan aanroepen voor cellen 2–3 schermen vóór scrollen — dit versnelt de perceptie, maar kan onnodige netwerkverzoeken veroorzaken.
NavigationStack (iOS 16+) beheert de schermstack anders dan NavigationView. Bij push van een nieuw scherm wordt onAppear alleen op het nieuwe scherm geactiveerd en het huidige scherm ontvangt geen onDisappear tot daadwerkelijke verwijdering. Bij pop vindt het omgekeerde proces plaats: onDisappear op het verlaten scherm, onAppear op het terugkerende scherm.
| Scenario | onAppear | onDisappear |
|---|---|---|
| Push | Nieuw scherm | Nee (scherm blijft in stack) |
| Pop | Terugkerend scherm | Verlaten scherm |
| Tabblad wisselen | Nieuw tabblad | Oud tabblad |
| Sheet sluiten | Ouderscherm | Geopende sheet |
Praktisch gebruik van onAppear omvat drie hoofdcategorieën: gegevens laden, animaties starten en analyse verzenden. Elk scenario vereist het in acht nemen van de kenmerken van de SwiftUI-levenscyclus om dubbele aanroepen en geheugenlekken te voorkomen.
Gegevens laden — het meest voorkomende scenario van onAppear. Binnen de sluiting wordt een Task gemaakt voor de async-aanroep en het resultaat wordt opgeslagen in @State of @StateObject. Het is belangrijk om te controleren of de gegevens niet opnieuw worden geladen met een isLoading-vlag of nil-controle.
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()
}
}
}
}
Guard against re-fetch — een cruciale praktijk. Als SwiftUI View opnieuw aanmaakt (bijvoorbeeld bij schermrotatie), wordt onAppear zonder guard opnieuw aangeroepen. Een alternatief is de .task-modificator die automatisch het vorige verzoek annuleert.
Binnenkomstanimatie gebruikt onAppear om state-variabelen te wijzigen die de animatie activeren via withAnimation of de animation-modificator. Typisch patroon: beginstatus (opacity 0, offset 100), overgang naar eindstatus (opacity 1, offset 0) bij verschijning.
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
}
}
}
}
Vertraging van 0.3 seconden creëert een sequentieel verschijningseffect als er meerdere van dergelijke kaarten op het scherm staan. Voor een lijst met geanimeerde elementen gebruikt u de index van het element als multiplicator van de vertraging.
.task — een SwiftUI-modificator toegevoegd in iOS 15 die het probleem van asynchrone bewerkingen in onAppear oplost. In tegenstelling tot onAppear accepteert .task een async-sluiting, beheert automatisch de levenscyclus ervan en annuleert deze bij het verdwijnen van View. Terwijl onAppear synchroon wordt uitgevoerd, start .task een asynchrone bewerking en laat SwiftUI deze annuleren bij onDisappear.
Het belangrijkste verschil — annuleringsbeheer. Wanneer .task een async-bewerking maakt, behoudt SwiftUI een verwijzing naar Task en roept automatisch cancel() aan bij verwijdering van View uit de hiërarchie. onAppear met Task {} erin annuleert de gestarte bewerking niet — deze blijft uitgevoerd worden, zelfs nadat View is verdwenen, wat een raceconditie of schrijven naar een reeds vrijgegeven instantie kan veroorzaken.
| Kenmerk | .onAppear | .task |
|---|---|---|
| iOS-versie | iOS 13+ | iOS 15+ |
| Async-ondersteuning | Alleen via Task {} | Native async/await |
| Automatische annulering | Nee | Bij verdwijnen van View |
| Herhaalde aanroep | Bij elke verschijning | Standaard eenmalig |
| Synchrone code | Ja | Alleen async |
Modificatorkeuze: gebruik onAppear voor synchrone acties (animaties, analyse, logs). Voor asynchroon laden van gegevens (API, Core Data, bestandssysteem) heeft .task de voorkeur — veiliger en schoner.
Fout 1: meervoudige aanroep door hercreatie van View. Wanneer SwiftUI de body van View opnieuw aanmaakt (@State-wijziging, schermrotatie), kan onAppear opnieuw worden aangeroepen. Oplossing — een laadvlag toevoegen of .equatable() gebruiken om onnodige hertekeningen te voorkomen. Volgens SwiftLee (2025) is 40% van de SwiftUI-bugs in productie precies gerelateerd aan herhaalde onAppear-aanroepen.
Fout 2: geheugenlek via sterke referentie. Als de onAppear-sluiting self zonder zwakke referentie vastlegt, ontstaat er een retain cycle met View. SwiftUI garandeert niet dat vastgelegde objecten worden genuld bij verdwijnen van View. Gebruik capture list [weak self] voor ViewModel of services.
Fout 3: uitvoering in de achtergrondthread. onAppear wordt uitgevoerd in de hoofdthread — dit is correct voor UI-bewerkingen. Maar als binnen onAppear een Task wordt gestart, zorg er dan voor dat de @State-update via MainActor.run plaatsvindt. Swift 5.9 en hoger keren automatisch terug naar MainActor, maar het is beter om @MainActor expliciet te specificeren.
Patroon met een laadvlag is de meest betrouwbare manier om te beschermen tegen duplicatie. Bewaar de vlag in @State of @StateObject en reset deze alleen bij handmatige update. Alternatief — gebruik .task in plaats van onAppear: .task wordt standaard niet herstart bij hertekening als de async-bewerking al wordt uitgevoerd.
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()
}
}
}
}
Veelgestelde vragen
viewDidLoad wordt eenmaal aangeroepen gedurende de levensduur van UIViewController, onafhankelijk van zichtbaarheid. .onAppear wordt aangeroepen bij elke toevoeging van View aan de hiërarchie — als View wordt verwijderd en opnieuw toegevoegd, wordt onAppear opnieuw geactiveerd. In NavigationView wordt viewDidLoad aangeroepen bij initialisatie en onAppear bij elke schermweergave.
Ja, via de wrapper Task { await asyncFunction() }. Voor async-bewerkingen heeft .task echter de voorkeur, omdat deze automatisch annulering beheert en geen handmatige Task-creatie vereist. .task garandeert ook annulering bij het verdwijnen van View, waardoor lekken worden voorkomen.
De oorzaak is het opnieuw aanmaken van de View-body door wijziging van @State, @Published of configuratie van de voorouder. SwiftUI kan View hertekenen als reactie op wijziging van elke waarneembare eigenschap. Bovendien roepen LazyVStack en List onAppear aan voor cellen die het zichtbare gebied naderen en opnieuw bij omhoog scrollen.
Ja, .onAppear is beschikbaar op alle SwiftUI-platforms: iOS 13+, watchOS 6+, tvOS 13+, macOS 10.15+. Het gedrag is identiek: de modificator wordt aangeroepen bij toevoeging van View aan de hiërarchie. Op watchOS wordt onAppear geactiveerd bij activering van de app vanuit de wachtstand, wat in het ontwerp moet worden meegenomen.
.onAppear accepteert geen parameters — alleen een Void-sluiting. Gebruik een sluiting die externe variabelen vastlegt om parameters door te geven. Een alternatieve benadering — het maken van een aangepaste onAppear-modificator met parameters via ViewModifier of een analoog van .onChange.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook