'SwiftUI - How to deinit a StateObject when navigating back?
I want my @StateObject
to be deinitialized as soon as possible after I navigate back, but it seems that the object is held in memory. "Deint ViewModel" is not being printed on back navigation, its first printed after I navigate again to the View I was coming from. Is there a way to release the @StateObject
from memory on back navigation?
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: TestView(), label: { Text("Show Test View") })
}
}
}
struct TestView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
Text("Test View")
}
}
final class ViewModel: ObservableObject {
deinit {
print("Deint ViewModel")
}
}
Solution 1:[1]
I don't have a brilliant answer on all situations that prevent the deinitialization the @StateObject, but I found that leaving background async tasks running prevents the deinitialization.
In my case, I had several cancellables registered to listen to PassthroughSubject and/or CurrentValueSubject (that I used to handle external changes on my model and exposing the result to the view), but I never cancelled them. As soon as I did it in the view using .onDisappear, it worked.
So my views all "subscribe" to the view model (I have a viewModel.subscribe() method) using .onAppear and then "unsubscribe" to the view model (I have a viewModel.subscribe() method) using .onDisappear. Doing so, the @StateObject is deinitialized when the view is dismissed.
Solution 2:[2]
I think you should use @ObservedObject private var viewModel: ViewModel
instead, then inject new ViewModel instance from outside of TestView
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | GregP |
Solution 2 | Long Vu |