我正在测试@ObservedObject,以测试SwiftUI如何处理模型的生命周期。
正如我现在所理解的,从WWDC的视频和文档中,创建模型对象的视图(一个采用ObservableObject的类)应该使用@StateObject。
从WWDC视频中,他们清楚地指出,@ObservedObject 并不拥有观察到的实例生命周期。
所以我创建了这个简单的设置:
struct TestParentView: View {
@ObservedObject var model:TestModel
var body: some View {
VStack {
Text("TEST TEXT. \(model.name)")
TestChildView(model: model)
}
}
}
struct TestParentView_Previews: PreviewProvider {
static var previews: some View {
TestParentView(model: TestModel())
}
}
struct TestChildView: View {
@ObservedObject var model:TestModel
var body: some View {
Button(action: {
print("change name")
model.changeName()
}, label: {
Text("Change Name")
})
}
}
struct TestChildView_Previews: PreviewProvider {
static var previews: some View {
TestChildView(model: TestModel())
}
}我在这里使用的模型是:
class TestModel:ObservableObject {
@Published var name:String = ""
let id = UUID()
func changeName() {
name = "\(UUID())"
}
deinit {
print("TestModel DEINIT. \(id)")
}
}当我运行这个应用程序时,我希望在TestParentView中创建的TestParentView实例至少在某个时候被去初始化,因为@ObservedObject并不拥有model的生命周期。
当我点击按钮来触发名称更改时,所有的更改都会生效,但是TestModel DEINIT不会被调用。
从这一切来看,TestParentView似乎有一个对TestModel的强引用,而且它从不让它离开。
那么,在这种情况下,当他们说@ObservedObject不管理model的生命周期时,这意味着什么呢?
如果TestModel没有管理模型的生命周期,为什么@ObservedObject从未调用过?
很明显我漏掉了什么。
发布于 2021-07-06 15:35:43
假设此视图:
struct Foo: View {
@ObservedObject var model = TestModel()
var body: some View {
Text(model.name)
}
}每次创建此视图时,它都会实例化TestModel的一个新实例。
SwiftUI视图实际上更像视图描述,在应用程序生命周期中创建和销毁了很多视图。因此,结构轻量级是很重要的。Foo视图并不是很轻量级,因为每次呈现传递它都会实例化一个新模型。
如果您使用@StateObject,框架将只在第一次实例化TestModel。在此之后,它将重用同一个实例。这使得它更有表现力。
经验法则:
如果视图创建自己的模型(如Foo视图),则使用@StateObject.
@ObservedObject.回答您的问题:“为什么TestModel DEINIT从未调用”.
您可以这样说:“当我运行这个应用程序时,我希望在TestParentView中创建的TestParentView实例至少在某个时候被去初始化”。
微妙的细节是,TestModel是而不是在TestParentView中创建的,它只是传入。
它在TestParentView_Previews中创建。而且,由于TestParentView_Previews的主体只执行一次,所以TestModel也只能初始化一次,因此永远不会被释放。
https://stackoverflow.com/questions/68246045
复制相似问题