这来自有关SwiftUI App协议的Apple文档:
@main
struct Mail: App {
@StateObject private var model = MailModel()
var body: some Scene {
WindowGroup {
MailViewer()
.environmentObject(model) // Passed through the environment.
}
Settings {
SettingsView(model: model) // Passed as an observed object.
}
}
}
在这种情况下,为什么需要使用@StateObject propertyWrapper?为什么普通财产还不够?
我怀疑“ App”结构是一个配置对象,就像SwiftUI中的视图一样?而且我们不能指望一旦读取尸体就可以在周围徘徊的那个结构吗?正确吗?
答案 0 :(得分:1)
根据Apple @StateObject
在model
中所做的保证
@StateObject private var model = MailModel()
将仅创建一次。与@ObservedObject
完全不同。因此,如果这对您不重要(或情况并非如此),并且您不需要在该级别进行观察,则可以使用常规属性声明。
答案 1 :(得分:0)
主要原因是进行预览,未初始化使用@StateObject
初始化的模型。 WWDC 2020 Structure your app for SwiftUI previews
8:19
第二,模型发生了变化,@StateObject
将使SwiftUI能够检测到变化并导致body
被重新计算,因为模型是在体内引用(两次)的,SwiftUI通过依赖关系知道跟踪。这意味着将使用模型中的新数据重新创建MailViewer
和SettingsView
。然后,如果这些View结构发生了任何变化,SwiftUI就会通过将新结构与先前返回的结构进行区分来检测到该变化,并使用需要进行的任何更新来更新屏幕,以使屏幕保持最新状态。
正如您所说,我们不能保证结构可以徘徊,实际上它们不是,它们是创建的,渲染的屏幕以及它们被扔掉了。这就是为什么我们使用属性包装器的原因,因此当再次创建该结构时,将为该属性使用相同的数据。在@StateObject
的情况下,对象仅创建一次,这是第一次对第一个结构的主体进行计算。如果不再创建结构,例如如果if语句将其排除,则该对象为deinit。如果将来再次创建该结构,则将创建一个新对象,这对Views而言比对Apps而言更多。这意味着状态对象的生命周期与屏幕上显示的View的生命周期紧密相关。
如果我们要使用常规属性在SwiftUI结构上初始化对象,则每次重新创建结构时都会创建这些对象,这是一个堆分配,会占用RAM并减慢SwiftUI的使用,应不惜一切代价避免