Description
I am trying to adapt my application to the new NavigationStack
introduced in IOS 16. I ended up with a strange behaviour when I have a @StateObject
variable in one of my views.
When I navigate (using the new .navigationDestination()
modifier) to a new view that has a @StateObject
the init()
block of that object will run twice.
The body of the view looks like this:
VStack {
Text("Param: \(intParam) and \(viewModel.someData)")
Button("Do Something") {
viewModel.buttonTapped()
}
}
BUT
If I remove the Button element the init()
of the @StateObject
will only run once.
Also
If I use the older NavigationLink(title:destination:)
element to navigate to the new page it will run the @StateObject
init()
once.
Full Code
struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
NavigationLink(value: 16) {
Text("Tap Me (IOS 16)")
}
NavigationLink("Tap Me (Older)") {
Page2(intParam: 45)
}
}
.navigationDestination(for: Int.self) { i in
Page2(intParam: i)
}
.navigationTitle("Navigation")
}
}
}
struct Page2: View {
@StateObject var viewModel = ViewModel()
let intParam: Int
init(intParam: Int) {
self.intParam = intParam
print("Page2 view created")
}
var body: some View {
VStack {
Text("Param: \(intParam) and \(viewModel.someData)")
Button("Do Something") {
viewModel.buttonTapped()
}
}
}
}
extension Page2 {
@MainActor class ViewModel: ObservableObject {
@Published var someData = "something"
init() {
print("Page2 viewmodel created")
}
func buttonTapped() {
print("do something")
}
}
}
Do you have any idea for the reason of this behaviour?
navigationDestination(for: destination:)
is getting called multiple times. You can remove all the remaining code and try and file a feedback with Apple