.onAppear — un modificator SwiftUI care execută o închidere la adăugarea View în ierarhia interfeței. Apelul are loc o singură dată per apariție a instanței pe ecran și servește ca punct principal pentru încărcarea datelor, pornirea animațiilor și trimiterea evenimentelor analitice. Conform Apple Developer Documentation (2026), onAppear garantează execuția înainte de primul randament, dar nu garantează apelul la fiecare reafișare dacă View rămâne în memorie. Citiți mai multe despre SwiftUI în materialul despre SwiftUI.
Principalele puncte
.onAppear — un modificator View în SwiftUI care acceptă o închidere Void și o execută în momentul când View devine vizibil pe ecran. Acest modificator face parte din sistemul de ciclu de viață al componentelor SwiftUI alături de .onDisappear și .task. Apple a introdus onAppear odată cu lansarea SwiftUI în iOS 13 și watchOS 6 ca înlocuitor pentru viewDidLoad din UIKit.
Din punct de vedere sintactic, .onAppear modifică orice View și returnează același View cu acțiunea atașată. Compilatorul SwiftUI apelează închiderea transmisă o singură dată când vizualizarea este adăugată în ierarhie și trece prin etapa de randare. Dacă View este șters și apoi re-adăugat (de exemplu, la derularea într-o listă), onAppear este apelat din nou — acest comportament devine adesea sursa unor bug-uri neașteptate.
Sintaxa de bază a modificatorului este minimalistă: onAppear fără parametri. În SwiftUI nu există posibilitatea de a transmite prioritate sau animație — închiderea se execută sincron în firul principal imediat după randare.
struct ContentView: View {
var body: some View {
Text("Salut, SwiftUI!")
.onAppear {
print("View a apărut pe ecran")
}
}
}
Limitări: onAppear nu suportă direct async/await. Pentru operații asincrone în interiorul închiderii este necesar Task {} sau o funcție separată cu async/await apelată prin Task.detached. Acest lucru face onAppear mai puțin convenabil pentru cererile de reȞa în comparație cu modificatorul .task.
.onAppear se integrează în conducta de randare SwiftUI la etapa layout+render. Când SwiftUI calculează corpul View și detectează o schimbare de ierarhie, pornește callback-urile onAppear pentru toate vizualizările nou adăugate. Ordinea de apel corespunde ordinii de imbricare: mai întâi onAppear la părinte, apoi la elementele copil.
O caracteristică importantă a SwiftUI — onAppear nu este legat de apariția fizică pe ecran. Modificatorul este apelat când View este adăugată în ierarhie, indiferent dacă este vizibilă utilizatorului (de exemplu, în afara ecranului în ScrollView). Acest lucru diferențiază SwiftUI de UIKit, unde viewWillAppear se activează doar la apariția reală.
Ordinea de apel respectă regula parent-first: VStack sau NavigationView primește mai întâi onAppear, apoi fiecare element copil în ordine. Acest lucru este critic pentru inițializarea resurselor partajate: dacă elementele copil depind de datele încărcate de părinte, ele trebuie să verifice disponibilitatea prin Optional.
struct ParentView: View {
var body: some View {
VStack {
ChildView()
ChildView()
}
.onAppear {
print("Parent onAppear — primul")
}
}
}
struct ChildView: View {
var body: some View {
Text("Copil")
.onAppear {
print("Child onAppear")
}
}
}
Rezultatul în consolă va fi: Parent onAppear — primul, apoi de două ori Child onAppear în ordinea poziției. Acest comportament este garantat de Apple și stabil în toate versiunile SwiftUI (iOS 13–18).
.onAppear are mai multe scenarii de apel care depind de container și navigare. În NavigationStack onAppear se declanșează la fiecare push al unui nou controler și la pop — pentru controlerul rădăcină. În TabView comutarea filelor apelează onAppear pentru fila afișată și onDisappear pentru cea ascunsă.
În List și ScrollView onAppear este apelat pentru celulele care au intrat în zona de vizibilitate sau se află în bufferul de pre-rendare. iOS 18 a introdus un mecanism prefetch care poate apela onAppear pentru celule cu 2–3 ecrane înainte de derulare — acest lucru accelerează percepția, dar poate provoca cereri de rețee inutile.
NavigationStack (iOS 16+) gestionează stiva de ecrane diferit de NavigationView. La push-ul unui nou ecran, onAppear se activează doar pe noul ecran, iar cel curent nu primește onDisappear până la ștergerea efectivă. La pop are loc procesul invers: onDisappear pe ecranul părăsit, onAppear pe ecranul revenit.
| Scenariu | onAppear | onDisappear |
|---|---|---|
| Push | Ecran nou | Nu (ecranul rămâne în stivă) |
| Pop | Ecranul revenit | Ecranul părăsit |
| Schimbare filă | Filă nouă | Filă veche |
| Sheet dismiss | Ecranul părinte | Sheet-ul deschis |
Utilizarea practică a onAppear acoperă trei categorii principale: încărcarea datelor, pornirea animațiilor și trimiterea analiticii. Fiecare scenariu necesită luarea în considerare a caracteristicilor ciclului de viață SwiftUI pentru a evita apelurile duplicate și scurgerile de memorie.
Încărcarea datelor — cel mai frecvent scenariu onAppear. În interiorul închiderii se creează un Task pentru apelul async, iar rezultatul este salvat în @State sau @StateObject. Este important să verificați dacă datele nu sunt încărcate din nou, folosind un flag isLoading sau verificarea pe 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()
}
}
}
}
Guard against re-fetch — o practică critică. Dacă SwiftUI recreează View (de exemplu, la rotirea ecranului), onAppear va fi apelat din nou fără guard. Alternativa este modificatorul .task, care anulează automat cererea anterioară.
Animația de intrare folosește onAppear pentru a modifica variabilele de stare care declanșează animația prin withAnimation sau modificatorul animation. Modelul tipic: stare inițială (opacity 0, offset 100), tranziție la starea finală (opacity 1, offset 0) la apariție.
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
}
}
}
}
Întârzierea de 0.3 secunde creează un efect de apariție secvențială dacă pe ecran sunt mai multe astfel de cartonașe. Pentru o listă de elemente animate, folosiți indexul elementului ca multiplicator al întârzierii.
.task — un modificator SwiftUI adăugat în iOS 15 care rezolvă problema operațiilor asincrone în onAppear. Spre deosebire de onAppear, .task acceptă o închidere async, gestionează automat ciclul său de viață și o anulează la dispariția View. În timp ce onAppear se execută sincron, .task pornește o operație asincronă și permite SwiftUI să o anuleze la onDisappear.
Diferența principală — gestionarea anulării. Când .task creează o operație async, SwiftUI păstrează o referință la Task și apelează automat cancel() la ștergerea View din ierarhie. onAppear cu Task {} în interior nu anulează operația pornită — aceasta continuă să se execute chiar și după ce View a dispărut, ceea ce poate cauza condiții de cursă sau scrierea într-o instanță deja eliberată.
| Caracteristică | .onAppear | .task |
|---|---|---|
| Versiune iOS | iOS 13+ | iOS 15+ |
| Suport async | Doar prin Task {} | Async/await nativ |
| Auto-anulare | Nu | La dispariția View |
| Reapelare | La fiecare apariție | Implicit o singură dată |
| Cod sincron | Da | Doar async |
Alegerea modificatorului: pentru acțiuni sincrone (animații, analitică, loguri) folosiți onAppear. Pentru încărcarea asincronă a datelor (API, Core Data, sistem de fițiere) .task este preferabil — mai sigur și mai curat.
Greșeala 1: apel multiplu din cauza recreării View. Când SwiftUI recreează corpul View (schimbarea @State, rotirea ecranului), onAppear poate fi apelat din nou. Soluția — adăugarea unui flag de încărcare sau utilizarea .equatable() pentru a preveni rerandările inutile. Conform SwiftLee (2025), 40% din bug-urile SwiftUI în producție sunt legate tocmai de apelurile repetate ale onAppear.
Greșeala 2: scurgere de memorie prin referință puternică. Dacă închiderea onAppear capturează self fără referință slabă, se creează un retain cycle cu View. SwiftUI nu garantează zeroirea obiectelor capturate la dispariția View. Folosiți capture list [weak self] pentru ViewModel sau servicii.
Greșeala 3: execuția în firul de fundal. onAppear se execută în firul principal — acest lucru este corect pentru operațiile UI. Dar dacă în interiorul onAppear este pornit un Task, asigurați-vă că actualizarea @State are loc prin MainActor.run. Swift 5.9 și versiunile superioare revin automat la MainActor, dar este mai bine să specificați @MainActor explicit.
Modelul cu un flag de încărcare este cea mai sigură modalitate de a vă proteja împotriva duplicării. Păstrați flag-ul în @State sau @StateObject și resetați-l doar la actualizarea manuală. Alternativa — utilizarea .task în loc de onAppear: .task implicit nu se reia la rerandare dacă operația async este deja în execuție.
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()
}
}
}
}
Întrebări frecvente
viewDidLoad este apelat o singură dată pe durata vieții UIViewController, independent de vizibilitate. .onAppear este apelat la fiecare adăugare a View în ierarhie — dacă View este șters și re-adăugat, onAppear se declanșează din nou. În NavigationView viewDidLoad este apelat la inițializare, iar onAppear — la fiecare afișare a ecranului.
Da, prin intermediul Task { await asyncFunction() }. Totuși, pentru operații async este preferabil .task, care gestionează automat anularea și nu necesită crearea manuală a Task. .task garantează, de asemenea, anularea la dispariția View, prevenind scurgerile.
Cauza este recrearea corpului View din cauza modificării @State, @Published sau a configurației strămoșului. SwiftUI poate reranda View ca răspuns la schimbarea oricărei proprietăți observabile. În plus, LazyVStack și List apelează onAppear pentru celulele care se apropie de zona vizibilă și din nou la derularea în sus.
Da, .onAppear este disponibil pe toate platformele SwiftUI: iOS 13+, watchOS 6+, tvOS 13+, macOS 10.15+. Comportamentul este identic: modificatorul este apelat la adăugarea View în ierarhie. Pe watchOS onAppear se declanșează la activarea aplicației din starea de așteptare, ceea ce trebuie luat în considerare în proiectare.
.onAppear nu acceptă parametri — doar o închidere Void. Pentru a transmite parametri, folosiți o închidere care capturează variabile externe. O abordare alternativă — crearea unui modificator personalizat onAppear cu parametri prin ViewModifier sau un analog al .onChange.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și