I'm making a Mac app using SwiftUI.
I have a simple 2 column NavigationView. The first view is a Sidebar containing a list, the second view is a detail view.
(I know NavigationView has been deprecated, but I can't use NavigationSplitView at the moment.)
When I launch the app, the init function on the detail view is being called for every row of the list (in toy example below, init 1-10 is printed to console). Is this the expected behavior or am I doing something wrong? In my real app, the init is used to create a core data fetch request, so calling it multiple times unnecessarily is undesirable.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
SidebarView()
EmptyView()
}
}
}
struct SidebarView: View {
var body: some View {
List{
ForEach((1...10), id: \.self){ i in
NavigationLink{
DetailView(myVar: i)
} label: {
Text("myVar \(i)")
}
}
}
}
}
struct DetailView: View {
@State var preVar:Int
init(myVar: Int) {
let _ = print("init \(myVar)")
self.preVar = myVar
}
var body: some View {
Text("Hello, World!")
}
}
This is expected behaviour, but it's only the init
that is called, so it's very lightweight.
The body
var is only called when the View is displayed.
This doesn't happen when using the new iOS 16 NavigationStack
as follows:
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
SidebarView(path: $path)
EmptyView()
}
}
}
struct SidebarView: View {
@Binding var path: NavigationPath
var body: some View {
List{
ForEach((1...10), id: \.self){ i in
NavigationLink("myVar \(i)", value: i)
}
}
.navigationDestination(for: Int.self) { i in
DetailView(myVar: i)
}
}
}