Lazy NavigationLink for SwiftUI

We don’t want to preload every ViewModel!

Steven Curtis
4 min readJan 24


Photo by Jamie Street on Unsplash

Difficulty: Beginner | Easy | Normal | Challenging

This article has been developed using Xcode 11.7, and Swift 5.2.4

You want to display some content in a `List`. You place a breakpoint and…well there is a nasty surprise.

Read on!



  • SwiftUI: A simple way to build user interfaces Across Apple platforms

The motivation

The destination views for navigation links are created when the body for the List is updated — and therefore raises the individual view models.

How did this situation occur?

The code

I’ve rather lazily (on topic for this article!) called the initial view ContentView.swift. Sorry for that.

This means that we create the SwiftUI view and feed it a view model in the SceneDelegate file.

let viewModel = ContentViewModel()

// Create the SwiftUI view that provides the window contents.
let contentView = ContentView(viewModel: viewModel)

// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window

and the content view takes us to a DetailView by displaying information from a view model in a List.

struct ContentView: View {
@ObservedObject var viewModel: ContentViewModel

init(viewModel: ContentViewModel) {
self.viewModel = viewModel

var body: some View {
NavigationView {
List {
ForEach(viewModel.animals, id: \.self) {
animal in
DetailView(viewModel: DetailViewModel(text: animal))
) {…