你确认了我对@ObservedObject和@EnvironmentObject的理解吗?
在我看来,当我们发送数据"时,使用@ObservedObject
是有用的;在行";在按顺序排列的视图之间;准备";在UIKit中,同时使用CCD_;"singleton";在UIKit中。我的问题是,我的代码是否正确地使用了这两个十进制?这是在实际开发中应用的方式吗?
我的模型被用作功能(IE URL会话、其他数据操作(的大脑
class ModelClass_ViaObservedObject: ObservableObject {
@Published var isOn: Bool = true
}
class ModelClass_ViaEnvironment: ObservableObject {
@Published var message: String = "default"
}
我的主视图
struct ContentView: View {
//way to send data in views step by step
@StateObject var modelClass_ViaObservedObject = ModelClass_ViaObservedObject()
//way to share data more or less like a singleton
@StateObject var modelClass_ViaEnvironment = ModelClass_ViaEnvironment()
var myBackgroundColorView: Color {
if modelClass_ViaObservedObject.isOn {
return Color.green
} else {
return Color.red
}
}
var body: some View {
NavigationView {
ZStack {
myBackgroundColorView
VStack {
NavigationLink(destination:
SecondView(modelClass_viaObservedObject: modelClass_ViaObservedObject)
) {
Text("Go to secondary view")
.padding()
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(.black, lineWidth: 1)
)
}
Text("text received from second view: (modelClass_ViaEnvironment.message)")
}
}
.navigationTitle("Titolo")
.navigationBarTitleDisplayMode(.inline)
}
.environmentObject(modelClass_ViaEnvironment)
}
}
我的第二视图
struct SecondView: View {
@Environment(.dismiss) var dismiss
@ObservedObject var modelClass_viaObservedObject: ModelClass_ViaObservedObject
//global data in environment, not sent step by step view by view
@EnvironmentObject var modelClass_ViaEnvironment: ModelClass_ViaEnvironment
var body: some View {
VStack(spacing: 5) {
Text("Second View")
Button("change bool for everyone") {
modelClass_viaObservedObject.isOn.toggle()
dismiss()
}
TextField("send back", text: $modelClass_ViaEnvironment.message)
Text(modelClass_ViaEnvironment.message)
}
}
}
不,我们使用@State
来查看数据,就像切换isOn
一样,它可以是单个值本身,也可以是包含多个值和可变函数的自定义结构。我们通过在子View中声明let
将其传递到View层次结构,或者如果需要写访问权限,则使用@Binding var
。无论我们是声明它为let
还是@Binding
,只要一个不同的值被传递到子View
的init
,SwiftUI就会自动调用body(只要它在body中被实际访问(。
@StateObject
是指当单个值或自定义结构不起作用时,我们需要视图数据的引用类型,即如果持久化或同步数据(但不使用新的async/await,因为我们使用.task
(。在调用body
之前(通常在它即将出现之前(,对象是init
,在不再需要View
时(通常在其消失之后(,对象为deinit
。
@EnvironmentObject
通常用于在@Published
属性中保存模型结构并负责保存或同步的存储对象,。不同之处在于,模型数据不与任何特定视图绑定,就像@State
和@EnvironmentObject
0用于视图数据一样。这个对象通常是一个singleton,一个用于应用程序,一个带有预览时的示例数据,因为它永远不应该被卸载。与@ObservedObject
相比,@EnvironmentObject
的优势在于,当我们只需要在层次结构的更底层时,我们不需要将它作为不需要对象的let
向下传递到每个视图。请注意,它必须作为let而不是@ObservedObject
传递的原因是,在中间视图中不必要地调用body,因为SwiftUI的依赖项跟踪不适用于仅对象的值类型。
以下是一些示例代码:
struct MyConfig {
var isOn = false
var message = ""
mutating func reset() {
isOn = false
message = ""
}
}
struct MyView: View {
@State var config = MyConfig() // grouping vars into their struct makes use of value semantics to track changes (a change to any of its properties is detected as a change to the struct itself) and offers testability.
var body: some View {
HStack {
ViewThatOnlyReads(config: config)
ViewThatWrites(config: $config)
}
}
}
struct ViewThatOnlyReads: View {
let config: MyConfig
var body: some View {
Text(config.isOn ? "It's on" : "It's off")
}
}
struct ViewThatWrites: View {
@Binding var config: MyConfig
var body: some View {
Toggle("Is On", isOn: $config.isOn)
}
}