.onAppear: princip fungování, životní cyklus a příklady ve SwiftUI

Autor: IT Sectr Publikováno: 2026-06-26 Doba čtení: 10 min

.onAppear — modifikátor SwiftUI, který provádí uzávěr při přidávání View do hierarchie rozhraní. Volání proběhne jednou za výskyt instance na obrazovce a slouží jako hlavní bod pro načítání dat, spouštění animací a odesílání analytických událostí. Podle Apple Developer Documentation (2026) onAppear zaručuje provedení před prvním vykreslením, ale nezaručuje volání při každém opakovaném zobrazení, pokud View zůstává v paměti. Více o SwiftUI si přečtěte v materiálu o SwiftUI.

Hlavní body

  • .onAppear — modifikátor SwiftUI pro provádění kódu při zobrazení View na obrazovce.
  • Jednorázovost — onAppear je volán jednou za životní cyklus View, pokud zůstává v paměti.
  • Načítání dat — hlavní scénář onAppear: fetch z API, čtení z Core Data nebo UserDefaults.
  • Animace — onAppear spouští vstupní animace: opacity, scale, offset se zpožděním.
  • Analytika — přes onAppear se odesílají události screen view, impression, page open.

Co je .onAppear?

.onAppear — modifikátor View ve SwiftUI, který přijímá uzávěr Void a provádí jej v okamžiku, kdy se View stane viditelným na obrazovce. Tento modifikátor je součástí systému životního cyklu komponent SwiftUI spolu s .onDisappear a .task. Apple představila onAppear spolu s vydáním SwiftUI v iOS 13 a watchOS 6 jako náhradu za viewDidLoad z UIKit.

.onAppear modifikuje libovolné View a vrací stejné View s připojenou akcí. Kompilátor SwiftUI volá předaný uzávěr jednou, když je pohled přidán do hierarchie a projde fází vykreslení. Pokud je View smazáno a poté znovu přidáno (například při posouvání v seznamu), onAppear je volán znovu — toto chování se často stává zdrojem neočekávaných chyb.

Syntaxe onAppear

Základní syntaxe modifikátoru je minimalistická: onAppear bez parametrů. Ve SwiftUI není možnost předat prioritu nebo animaci — uzávěr se provádí synchronně v hlavním vlákně ihned po vykreslení.

swift
struct ContentView: View {
    var body: some View {
        Text("Ahoj SwiftUI!")
            .onAppear {
                print("View se objevilo na obrazovce")
            }
    }
}

Omezení: onAppear nepodporuje přímo async/await. Pro asynchronní operace uvnitř uzávěru je potřeba Task {} nebo samostatná funkce async/await volaná přes Task.detached. To činí onAppear méně pohodlným pro síťové požadavky ve srovnání s modifikátorem .task.

Jak funguje .onAppear v životním cyklu View

.onAppear se začleňuje do vykreslovací pipeline SwiftUI ve fázi layout+render. Když SwiftUI vypočítá tělo View a detekuje změnu hierarchie, spustí callbacky onAppear pro všechny nově přidané pohledy. Pořadí volání odpovídá pořadí vnoření: nejprve onAppear u rodiče, poté u potomků.

Důležitá vlastnost SwiftUI — onAppear není vázán na fyzický výskyt na obrazovce. Modifikátor je volán, když je View přidáno do hierarchie, bez ohledu na to, zda je viditelné pro uživatele (např. mimo obrazovku v ScrollView). To odlišuje SwiftUI od UIKit, kde viewWillAppear funguje pouze při skutečném zobrazení.

Pořadí volání onAppear

Pořadí volání se řídí pravidlem parent-first: VStack nebo NavigationView nejprve obdrží onAppear, poté každý potomek v pořadí. To je kritické pro inicializaci sdílených zdrojů: pokud potomci závisí na datech načítaných rodičem, musí zkontrolovat dostupnost přes Optional.

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

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

Výstup do konzole bude: Parent onAppear — první, poté dvakrát Child onAppear v pořadí pozice. Toto chování je garantováno Apple a stabilní ve všech verzích SwiftUI (iOS 13–18).

Kdy je .onAppear volán

.onAppear má několik scénářů volání, které závisí na kontejneru a navigaci. V NavigationStack se onAppear spouští při každém push nového ovladače a při pop — pro kořenový ovladač. V TabView přepínání karet volá onAppear pro zobrazenou kartu a onDisappear pro skrytou.

V List a ScrollView je onAppear volán pro buňky, které vstoupily do oblasti viditelnosti nebo jsou v bufferu předvykreslení. iOS 18 zavedl mechanismus prefetch, který může volat onAppear pro buňky 2–3 obrazovky před posouváním — to zrychluje vnímání, ale může způsobovat zbytečné síťové požadavky.

Charakteristiky volání v NavigationStack

NavigationStack (iOS 16+) spravuje zásobník obrazovek jinak než NavigationView. Při push nové obrazovky se onAppear aktivuje pouze na nové obrazovce a aktuální obrazovka neobdrží onDisappear až do skutečného smazání. Při pop probíhá opačný proces: onDisappear na opouštěné obrazovce, onAppear na vracející se.

ScénářonAppearonDisappear
PushNová obrazovkaNe (obrazovka zůstává v zásobníku)
PopVracející se obrazovkaOpouštěná obrazovka
Přepnutí kartyNová kartaStará karta
Zavření sheetuRodičovská obrazovkaOtevřený sheet

Příklady použití .onAppear

Praktické použití onAppear zahrnuje tři hlavní kategorie: načítání dat, spouštění animací a odesílání analytiky. Každý scénář vyžaduje zohlednění charakteristik životního cyklu SwiftUI, aby se předešlo duplicitním voláním a únikům paměti.

Načítání dat z API

Načítání dat — nejčastější scénář onAppear. Uvnitř uzávěru je vytvořen Task pro async volání a výsledek je uložen v @State nebo @StateObject. Je důležité zkontrolovat, zda data nejsou načítána znovu, pomocí flagu isLoading nebo kontroly 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()
            }
        }
    }
}

Guard against re-fetch — kritická praxe. Pokud SwiftUI znovu vytvoří View (například při otočení obrazovky), onAppear bude bez guardu znovu volán. Alternativou je modifikátor .task, který automaticky ruší předchozí požadavek.

Spuštění vstupní animace

Vstupní animace používá onAppear ke změně stavových proměnných, které spouštějí animaci přes withAnimation nebo modifikátor animation. Typický vzor: počáteční stav (opacity 0, offset 100), přechod do konečného (opacity 1, offset 0) při zobrazení.

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
                }
            }
    }
}

Zpoždění 0,3 vteřiny vytváří efekt postupného zobrazování, pokud je na obrazovce několik takových karet. Pro seznam animovaných prvků použijte index prvku jako násobič zpoždění.

.onAppear vs .task — v čem je rozdíl

.task — modifikátor SwiftUI přidaný v iOS 15, který řeší problém asynchronních operací v onAppear. Na rozdíl od onAppear .task přijímá async uzávěr, automaticky spravuje jeho životní cyklus a ruší jej při zmizení View. Zatímco onAppear se provádí synchronně, .task spouští asynchronní operaci a umožňuje SwiftUI ji zrušit při onDisappear.

Hlavní rozdíl — správa rušení. Když .task vytvoří async operaci, SwiftUI uchovává odkaz na Task a automaticky volá cancel() při odstranění View z hierarchie. onAppear s Task {} uvnitř nezruší spuštěnou operaci — ta pokračuje v provádění i poté, co View zmizí, což může způsobit závodní stav nebo zápis do již uvolněné instance.

Vlastnost.onAppear.task
Verze iOSiOS 13+iOS 15+
Async podporaPouze přes Task {}Nativní async/await
Automatické rušeníNePři zmizení View
Opakované voláníPři každém zobrazeníVýchozí jednou
Synchromní kódAnoPouze async

Výběr modifikátoru: pro synchronní akce (animace, analytika, logy) použijte onAppear. Pro asynchronní načítání dat (API, Core Data, souborový systém) je .task preferovaný — bezpečnější a čistější.

Typické chyby s .onAppear

Chyba 1: vícenásobné volání kvůli přetvoření View. Když SwiftUI znovu vytvoří tělo View (změna @State, otočení obrazovky), onAppear může být volán znovu. Řešení — přidání flagu načítání nebo použití .equatable() k zabránění zbytečným překreslením. Podle SwiftLee (2025) 40% chyb SwiftUI v produkci souvisí právě s opakovanými voláními onAppear.

Chyba 2: únik paměti přes silný odkaz. Pokud uzávěr onAppear zachytí self bez slabého odkazu, vznikne retain cycle s View. SwiftUI nezaručuje vynulování zachycených objektů při zmizení View. Použijte capture list [weak self] pro ViewModel nebo služby.

Chyba 3: provedení v pozadí vlákna. onAppear se provádí v hlavním vlákně — to je správné pro UI operace. Ale pokud je uvnitř onAppear spuštěn Task, ujistěte se, že aktualizace @State probíhá přes MainActor.run. Swift 5.9 a vyšší se automaticky vracejí na MainActor, ale je lepší explicitně uvést @MainActor.

Jak se vyhnout opakovaným voláním

Vzor s flagem načítání je nejspolehlivější způsob ochrany před duplikováním. Uchovávejte flag v @State nebo @StateObject a resetujte jej pouze při ruční aktualizaci. Alternativa — použití .task místo onAppear: .task se výchozí nespouští znovu při překreslení, pokud async operace již běží.

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()
            }
        }
    }
}

Často kladené otázky

Čím se .onAppear liší od viewDidLoad v UIKit?

viewDidLoad je volán jednou za život UIViewController, nezávisle na viditelnosti. .onAppear je volán při každém přidání View do hierarchie — pokud je View smazáno a znovu přidáno, onAppear se znovu aktivuje. V NavigationView je viewDidLoad volán při inicializaci a onAppear — při každém zobrazení obrazovky.

Lze volat async funkci uvnitř .onAppear?

Ano, přes obal Task { await asyncFunction() }. Nicméně pro async operace je preferován .task, protože automaticky spravuje rušení a nevyžaduje ruční vytváření Task. .task také garantuje zrušení při zmizení View, čímž předchází únikům.

Proč je .onAppear volán několikrát?

Příčinou je přetvoření těla View kvůli změně @State, @Published nebo konfigurace předka. SwiftUI může překreslit View jako reakci na změnu libovolné pozorovatelné vlastnosti. Navíc LazyVStack a List volají onAppear pro buňky, které se přibližují k viditelné oblasti, a znovu při posouvání nahoru.

Funguje .onAppear na watchOS a tvOS?

Ano, .onAppear je dostupný na všech platformách SwiftUI: iOS 13+, watchOS 6+, tvOS 13+, macOS 10.15+. Chování je identické: modifikátor je volán při přidání View do hierarchie. Na watchOS se onAppear spouští při aktivaci aplikace z pohotovostního režimu, což je třeba zohlednit v návrhu.

Jak předat parametry do .onAppear?

.onAppear nepřijímá parametry — pouze Void uzávěr. Pro předání parametrů použijte uzávěr, který zachycuje externí proměnné. Alternativní přístup — vytvoření vlastního onAppear modifikátoru s parametry přes ViewModifier nebo analog .onChange.

Shrnutí

  • .onAppear — modifikátor SwiftUI pro provádění kódu při přidání View do hierarchie rozhraní.
  • Jednorázové volání — onAppear je volán jednou na instanci View, pokud zůstává v paměti.
  • Parent-first pořadí — rodičovské View dostávají onAppear dříve než potomci.
  • Hlavní scénáře — načítání dat, spouštění animací, odesílání analytiky.
  • .task je preferovaný pro async operace kvůli automatickému rušení při zmizení View.
  • Guard kontrola — povinná pro ochranu před opakovanými voláními při překreslení View.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také