这是使用@ObservedObject和@EnvironmentObject的正确方式吗



你确认了我对@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,只要一个不同的值被传递到子Viewinit,SwiftUI就会自动调用body(只要它在body中被实际访问(。

@StateObject是指当单个值或自定义结构不起作用时,我们需要视图数据的引用类型,即如果持久化或同步数据(但不使用新的async/await,因为我们使用.task(。在调用body之前(通常在它即将出现之前(,对象是init,在不再需要View时(通常在其消失之后(,对象为deinit

@EnvironmentObject通常用于在@Published属性中保存模型结构并负责保存或同步的存储对象,。不同之处在于,模型数据不与任何特定视图绑定,就像@State@EnvironmentObject0用于视图数据一样。这个对象通常是一个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)
}
}

相关内容

  • 没有找到相关文章

最新更新