我对 SwiftUI 的 NavigationView 堆栈中的内存管理如何工作有疑问。我有一个视图,其中我声明了 NavigationView 和 NavigationLink,NavigationLink 的目标参数内部是我的 TestView。导航效果很好,但是当我从堆栈中弹出视图(fe 向上后退按钮)时,控制台中不会打印 deinit,并且仍然可以在内存图中找到 TestViewModel。当不再需要我的 TestViewModel 时,如何取消它的初始化?
/// 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)
}
}
更新 添加了内存图屏幕截图,我已经忘记了。
更新
在导航工作的真实设备上进行了测试。看起来,视图模型在弹出视图时没有取消初始化,而是在再次推送时再次初始化。但是问题仍然存在,有没有办法在导航堆栈中弹出视图时取消初始化视图模型?
TestViewModel init
TestViewModel deinit
TestViewModel init
此外,当我向堆栈添加另一个视图时,行为会发生一些变化。现在 second 的视图视图模型将导致泄漏,但 first 将按预期取消初始化。
First view push
TestViewModel init
Second view push
TestViewModel2 init
Second view pop
First view pop
TestViewModel deinit