Hi
I’ve recently encountered a weird instantiation behaviour where the wrapped value of a @StateObject could be created twice. It happens when the @StateObject is instantiated in the init function of a View. Only if the View
is embedded in a NavigationStack
AND there is some state driven component inside the View
.
Here’s a self contained code sample that demonstrates that. Does anybody know what’s going on?
Thanks.
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
MainView(resolver: makeDependency)
}
}
}
func makeDependency() -> MyDependency {
print("makeDependency") // printed twice
return MyDependency(value: "5")
}
class MyDependency: ObservableObject {
@Published
var value: String
init(value: String) {
self.value = value
}
}
struct MainView: View {
var resolver: () -> MyDependency
@State var text = ""
init(resolver: @escaping () -> MyDependency) {
self.resolver = resolver
}
var body: some View {
NavigationStack { // if commented, no double dep resolution
WithDependencyView(resolver: resolver) { dependency in
VStack {
Text(dependency.value)
TextField("Input", text: $text, axis: .horizontal) // if commented, no double dep resolution
}
}
}
}
}
// equivalent to WithViewStore
struct WithDependencyView<Content: View>: View {
@StateObject var dependency: MyDependency
let content: (MyDependency) -> Content
init(
resolver: @escaping () -> MyDependency,
@ViewBuilder content: @escaping (MyDependency) -> Content
) {
self._dependency = StateObject(wrappedValue: resolver())
self.content = content
}
var body: some View {
self.content(self.dependency)
}
}