In the example below, there are 2 views linked through NavigationLink in the NavigationView: the root ContentView and the subordinate ListView.
struct ContentView: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State private var counter = 0
var body: some View {
NavigationView{
VStack{
Text("counter: \(counter)")
.onReceive(timer) { _ in
counter += 1
}
NavigationLink(destination: ListView()) {
Text("List").padding()
}
}
}
}
}
struct ListView: View {
let items = ["first", "second", "third"]
init() {
print(Date(), "init ListView")
}
var body: some View {
List{
ForEach(items, id: \.self) { item in
NavigationLink(destination: ItemView(item: item)) {
Text(item).padding()
}
}
}
}
}
In the ContentView, the counter variable changes every second, which causes the ContentView to be redrawn and the ListView to be permanently initialized. The ListView is initialized and the "init ListView" displayed every second regardless of what is currently on the ContentView or ListView. From the point of view of the data model, the ListView does not depend in any way on counter and on the state of the ContentView.
In a real application, the situation is much more complicated and costly. ContentView displays a MapView whose state is constantly changing, and ListView displays a list of recorded routes. The ListView initialization contains some pretty expensive logic. Constantly initializing the ListView takes time, although it is really only required when switching to the ListView, and not every time the ContentView changes state.
What is the correct way to make the NavigationView work while getting rid of the ListView's dependency on the ContentView state change?