swiftui · note · architecture · performance

Why onAppear Is Not Lifecycle

Published February 27, 2026 · 1 min read · intermediate

Context

onAppear can run multiple times, so treating it as a one-time lifecycle hook causes fragile behavior.


The snippet

struct FeedView: View {
    @State private var hasLoaded = false

    var body: some View {
        List(0..<20, id: \.self) { index in
            Text("Row \(index)")
        }
        .task {
            guard !hasLoaded else { return }
            hasLoaded = true
            await loadFeed()
        }
    }

    private func loadFeed() async {
        // async fetch
    }
}

Why this works

task models asynchronous work explicitly and composes better with cancellation than assuming onAppear means “screen started once.”


Use it when…

  • you need first-load behavior guarded by state
  • you need cancellation-aware async work
  • the view may appear/disappear repeatedly

Avoid it when…

  • you put heavy synchronous work in body or onAppear
  • you assume one appearance equals one lifetime
  • you trigger network calls without idempotency guards

Takeaway: Treat onAppear as a visibility signal, not as lifecycle truth.

Next steps