I have a question on how memory management works in SwiftUI's NavigationView stack. I have a view, in which I have declared NavigationView and NavigationLink, inside destination parameter of NavigationLink is my TestView. Navigation works good, but when I pop view from stack (f. e. up back button) deinit is not printed in console and TestViewModel can still be found in memory graph. How do I deinitialize my TestViewModel, when it's not needed anymore ?
/// First view in application
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello, leak!")
NavigationLink(
destination: TestView(viewModel: TestViewModel()),
label: { Text("Create leak π€·ββοΈ") }
)
}
}
}
}
/// Just simple class for init and deinit print
class TestViewModel: ObservableObject {
@Published var text = "Test"
init() {
print("TestViewModel init")
}
deinit {
print("TestViewModel deinit")
}
}
/// Second view, which is poped from stack
private struct TestView: View {
@ObservedObject var viewModel: TestViewModel
var body: some View {
Text(viewModel.text)
}
}
UPDATE Added memory graph screenshot, which I preveiosly forget.
UPDATE
Tested on real device, where navigation works. It looks like, view model is not deinitializad, when poping view, but initialized again, when pushing another time. But question still remains, is there a way to deinit view model, when popping view in navigation stack ?
TestViewModel init
TestViewModel deinit
TestViewModel init
Also, when I add another view to stack, behaviour changes a bit. Now second's view view model will cause leak, but first will be deinitialized as expected.
First view push
TestViewModel init
Second view push
TestViewModel2 init
Second view pop
First view pop
TestViewModel deinit