@ObservedObject模型生命周期



我正在测试@ObservedObject,以测试SwiftUI如何处理模型的生命周期。

我现在从WWDC视频和文档中了解到,创建模型对象(采用ObservableObject的类(的View应该使用@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中创建的TestModel实例至少在某个时候被取消初始化,因为@ObservedObject不拥有model的生命周期。

当我点击按钮触发名称更改时,一切都正常,但TestModel DEINIT从未被调用。

从所有这些来看,TestParentView似乎有一个对TestModel的strong引用,并且它从未放弃它。

那么,当他们说@ObservedObject在这种情况下不管理model的生命周期时,他们的意思是什么呢?

如果@ObservedObject不管理模型的生命周期,为什么永远不会调用TestModel DEINIT?

我显然错过了什么。

假设此视图:

struct Foo: View {
@ObservedObject var model = TestModel()
var body: some View {
Text(model.name)
}
}

每次创建此视图时,它都会实例化TestModel的一个新实例。

SwiftUI视图实际上更像是在应用程序生命周期中创建和销毁的视图描述。因此,结构的轻量级是很重要的。Foo视图不是很轻量级,因为它的每个渲染过程都会实例化一个新模型。

如果您改为使用@StateObject,那么框架将只在第一次实例化一个TestModel。之后,它将重用相同的实例。这使它更具表演性。

经验法则:

  • 如果视图创建了自己的模型(例如Foo视图(,请使用@StateObject
  • 如果模型是从外部传入的,请使用@ObservedObject

要回答您的问题:";为什么测试模型DEINIT从未被称为">

您声明:";当我运行这个应用程序时,我希望在TestParentView中创建的TestModel实例至少在某个时候被取消初始化;。

微妙的细节是,TestModel是而不是TestParentView中创建的,它只是传入的。

它是在TestParentView_Previews中创建的。由于TestParentView_Previews的主体只执行一次,所以TestModel也只初始化一次,因此永远不会被释放。

相关内容

  • 没有找到相关文章

最新更新