SwiftUI NavigationLink loads destination view immediately, without clicking
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
NavigationLink in SwiftUI initializes its destination view immediately when the parent view renders, not when the user taps the link. This means the destination's init() runs, network requests fire, and resources are allocated before the user ever navigates. This is by design. SwiftUI pre-renders views for transition animations. The fix is to wrap the destination in a lazy container or use the NavigationLink(value:) API introduced in iOS 16.
The Problem
When ContentView appears, all 10 DetailView initializers run. If DetailView makes API calls in init(), you get 10 unnecessary network requests.
Fix 1: Lazy Destination Wrapper (iOS 13+)
Create a wrapper that defers view creation until navigation occurs:
The @autoclosure captures the DetailView(id: index) expression without evaluating it. The view is only created when SwiftUI renders LazyView.body, which happens during navigation.
Fix 2: NavigationLink with value (iOS 16+)
Use the modern navigationDestination modifier:
NavigationLink(value:) does not take a destination view. It only passes a value. The navigationDestination modifier creates the view lazily when navigation occurs.
Fix 3: Move Expensive Work to onAppear
Keep the init lightweight and defer work to onAppear:
onAppear fires only when the view is displayed, not when it is initialized. This is the most important pattern. Even with lazy loading, you should use onAppear for expensive operations.
Fix 4: Use @StateObject for ViewModels
.task is like onAppear but automatically cancels when the view disappears, making it ideal for async work.
Fix 5: Conditional NavigationLink
Only create the link when data is ready:
This programmatic approach creates the destination only when selectedId is set.
Why Does SwiftUI Do This?
SwiftUI pre-renders destination views for:
- Transition animations: The destination must be measured and laid out before the push animation starts
- Prefetching: SwiftUI may cache destination views for faster navigation
- Declarative model: Views are descriptions of UI, not live objects. SwiftUI evaluates the full view tree to determine what to render
This is different from UIKit where a view controller is pushed and its viewDidLoad runs on demand.
Common Pitfalls
- Network calls in init: The most common mistake. Move all fetching to
onAppear,.task, or a method triggered after navigation. Never make API calls in a view's initializer. - Heavy @StateObject initialization:
@StateObjectcreation is deferred by SwiftUI, but if you pass complex parameters to its init, the parameter expressions are still evaluated eagerly. Keep parameter construction cheap. - Using NavigationView instead of NavigationStack:
NavigationViewis deprecated in iOS 16.NavigationStackwithnavigationDestination(for:)provides lazy destination creation by default. - Forgetting LazyView in lists: In a
ListorForEachwith many items, everyNavigationLinkdestination initializes immediately. UseLazyViewfor all links in lists. .onAppearfiring multiple times: In some SwiftUI versions,onAppearcan fire more than once (tab switches, sheet dismissals). Use a flag to prevent duplicate work:if !hasLoaded { loadData(); hasLoaded = true }.
Summary
NavigationLinkinitializes its destination view immediately, not on tap- Use
LazyViewwrapper to defer destination creation (iOS 13+) - Use
NavigationStackwithnavigationDestination(for:)for lazy creation (iOS 16+) - Move expensive operations (network, database, computation) to
onAppearor.task - Use
@StateObjectfor view models and trigger data loading in.task, notinit() - This behavior is by design for SwiftUI's declarative rendering model
Related reading
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.