我对SwiftUI的NavigationView堆栈中的内存管理工作方式有疑问。我有一个视图,其中声明了NavigationView和NavigationLink,NavigationLink的目标参数内是我的TestView。导航效果很好,但是当我从堆栈中弹出视图(例如,向上后退按钮)时,不会在控制台中打印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
此外,当我将另一个视图添加到堆栈中时,行为也会有所变化。现在,第二个视图的视图模型将导致泄漏,但第一个将按预期被取消初始化。
First view push
TestViewModel init
Second view push
TestViewModel2 init
Second view pop
First view pop
TestViewModel deinit
答案 0 :(得分:1)
我遇到了同样的问题,花了很多时间来解决。终于我明白了!使用ERROR: PyAudio-0.2.11-cp39-cp39-win32.whl is not a supported wheel on this platform.
。添加是NavigationView的功能:
.navigationViewStyle(StackNavigationViewStyle())
答案 1 :(得分:1)
当我看着Data Essentials in SwiftUI时,我找到了问题的答案。这是新的StateObject属性包装器(我找不到文档,但是这里是post对其进行了描述)。 现在,当我希望我的数据仅存在于视图范围内时,可以使用@StateObject,而无需进行任何改动。