如果我创建一个新的@State
变量,它什么时候被销毁?它是否能在父UIHostingController
的一生中生存?
据我所知,它没有记录在案。这是相关的,因为如果我在视图层次结构中的某个位置将ObservableObject
创建为State
,我不知道如何在自己之后进行清理。
import SwiftUI
struct Example: View {
@State private var foo = Foo()
var body: some View {
Text("My Great View")
}
}
class Foo: ObservableObject {
deinit {
// When will this happen?
print("Goodbye!")
}
}
假设:
struct Example: View {
@State private var foo = Foo()
var body: some View {
Text("My Great View")
}
}
class Foo: ObservableObject {
init() {
print(#function)
}
deinit {
print(#function)
}
}
问题是View
类型是struct
,而它的body
不是实时执行的函数集合,而是在呈现View
的body
的同时实际初始化的函数。
问题场景:
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
NavigationLink(destination: Example()) {
Text("Test")
}
}
}
}
如果您注意到,甚至在导航发生之前就调用了Example.init
,而在弹出窗口中根本不调用Example.deinit
。原因是当ContentView
被初始化时,它也必须初始化它的body
中的所有内容。因此Example.init
将被调用。
当我们导航到Example
时,它已经初始化,因此不会再次调用Example.init
。当我们跳出Example
时,我们只是回到ContentView
,但由于可能再次需要Example
,而且它不是实时创建的,因此不会被销毁。
只有在必须完全移除CCD_ 21时才会调用CCD_。
我不确定这一点,但在这里发现了另一篇关于类似问题的文章:
- SwiftUI和如何不初始化可绑定对象
为了证明这一点,让我们确保ContentView
被完全移除
以下示例使用操作表来显示它,并将其从视图层次结构中删除。
工作场景:
struct ContentView: View {
@State var isPresented = false
var body: some View {
Button(action: { self.isPresented.toggle() }) {
Text("Test")
}
.sheet(isPresented: $isPresented) {
Example()
.onTapGesture {
self.isPresented.toggle()
}
}
}
}
PS:这适用于类,即使没有声明为@State
,也与ObservableObject
没有任何关系。
在iOS 14中,正确的方法是使用@StateObject
。没有安全的方法将引用类型存储在@State
中。