SwiftUI - 返回时如何取消初始化 StateObject?

问题描述 投票:0回答:4

我希望我的

@StateObject
在我导航回来后尽快被取消初始化,但似乎该对象被保存在内存中。 “Deint ViewModel”没有打印在返回导航上,它是在我再次导航到我来自的视图后第一次打印的。有没有办法在后退导航时从内存中释放
@StateObject

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")
    }
}
swift navigation swiftui
4个回答
3
投票

对于阻止 @StateObject 去初始化的所有情况,我没有一个出色的答案,但我发现让后台异步任务运行可以防止去初始化。

就我而言,我注册了几个可取消项来监听 PassthroughSubject 和/或 CurrentValueSubject (我用来处理模型上的外部更改并将结果公开给视图),但我从未取消过它们。当我使用 .onDisappear 在视图中执行此操作后,它就起作用了。

所以我的视图都使用 .onAppear“订阅”视图模型(我有一个 viewModel.subscribe() 方法),然后使用 .onDisappear“取消订阅”视图模型(我有一个 viewModel.subscribe() 方法)。这样做,当视图关闭时,@StateObject 将被取消初始化。


2
投票

添加 GregP 的答案: 如果您已删除

cancellables
上的所有
onDisappear
并且
deinit
仍未被调用,您可以使用调试内存图

导航到该对象,查看其树并查看还有什么引用它。 例如我的它看起来像这样:

因为有另一个对象引用该对象,所以它没有从内存(ARC)中删除。所以我所要做的就是将其从代表中删除,并取消

cancellables
deinit
被调用


0
投票

使用

NavigationStack
代替
navigationView

@StateObject private var viewModel

使用

NavigationView
时不会被定义,但这是我使用
NavigationStack
时定义的。

enter image description here


-1
投票

我认为你应该使用

@ObservedObject private var viewModel: ViewModel
来代替,然后从 TestView 外部注入新的 ViewModel 实例

© www.soinside.com 2019 - 2024. All rights reserved.