在 View 之间共享变量的最佳实践是什么? 我的应用程序只有一个 View 。但随着它变得越来越复杂,我想我应该把它分成几个 View 。还要分离方法。 我从这样的事情开始:
struct ContentView: View {
@State var str: String = "String"
var body: some View {
VStack(alignment: .leading) {
Text(str)
TextField("Input", text: $str)
Button("button", action: { doSomething() })
}.padding()
}
func doSomething() {
str = str + " " + str
}
}
想去那里:
class GlobalVars: ObservableObject {
@Published var str: String = "Initial String"
}
struct ContentView: View {
@ObservedObject var globalvars = GlobalVars()
var body: some View {
VStack(alignment: .leading) {
DisplayView()
EditView()
ControlView()
}.padding()
}
}
struct DisplayView: View {
@Binding var str: String
var body: some View {
Text(self.globalvars.str)
}
}
struct EditView: View {
@Binding var str: String
var body: some View {
TextField("Input", text: self.$str)
}
}
struct ControlView: View {
@Binding var str: String
var body: some View {
Button("button", action: { doSomething() })
}
}
func doSomething() {
@Binding var str: String
self.str = self.str + " " + self.str
}
我尝试使用@Published、@ObservedObject 和@Binding。但别明白。感谢您提前提供任何指示。
最佳答案
有多种方法可以解决这个问题。
我的选择可能是将绑定(bind)传递给您需要访问的变量。可能看起来像这样:
class GlobalVars: ObservableObject {
@Published var str: String = "Initial String"
}
struct ContentView: View {
@ObservedObject var globalvars = GlobalVars()
var body: some View {
VStack(alignment: .leading) {
DisplayView(str: globalvars.str) //don't need a binding here since it doesn't get modified
EditView(str: $globalvars.str)
ControlView(str: $globalvars.str)
}.padding()
}
}
struct DisplayView: View {
var str: String //don't need a binding here since it doesn't get modified
var body: some View {
Text(str)
}
}
struct EditView: View {
@Binding var str: String
var body: some View {
TextField("Input", text: $str)
}
}
struct ControlView: View {
@Binding var str: String
var body: some View {
Button("button", action: { doSomething() })
}
func doSomething() {
str = str + " " + str
}
}
请注意,现在在 ContentView
,有一个参数传递给每个 subview ,其中包含到 $
的绑定(bind)(使用 GlobalVars
符号) str
属性。
此外,doSomething
被移入ControlView
的 body
您还可以使用EnvironmentObject 来处理此问题。我个人不太喜欢这种方法,因为我宁愿明确地看到我的参数的去向。它还允许 subview 访问整个 ObservableObject,但这并不是真正必要的。但是,它向您展示了原理:
class GlobalVars: ObservableObject {
@Published var str: String = "Initial String"
}
struct ContentView: View {
@ObservedObject var globalvars = GlobalVars()
var body: some View {
VStack(alignment: .leading) {
DisplayView()
EditView()
ControlView()
}.padding()
.environmentObject(globalvars)
}
}
struct DisplayView: View {
@EnvironmentObject var globalvars : GlobalVars
var body: some View {
Text(globalvars.str)
}
}
struct EditView: View {
@EnvironmentObject var globalvars : GlobalVars
var body: some View {
TextField("Input", text: $globalvars.str)
}
}
struct ControlView: View {
@EnvironmentObject var globalvars : GlobalVars
var body: some View {
Button("button", action: { doSomething() })
}
func doSomething() {
globalvars.str = globalvars.str + " " + globalvars.str
}
}
请注意,现在,globalvars
通过将 .environmentObject
放置在 View 层次结构中来传递给子级。每个 subview 都可以通过声明 @EnvironmentObject var globalvars : GlobalVars
属性来访问它。
您还可以采用一种混合模型,将 ObservableObject 作为参数显式传递给 subview :
struct ContentView: View {
@ObservedObject var globalvars = GlobalVars()
var body: some View {
VStack(alignment: .leading) {
DisplayView(globalvars: globalvars)
}.padding()
.environmentObject(globalvars)
}
}
struct DisplayView: View {
@ObservedObject var globalvars : GlobalVars
var body: some View {
Text(globalvars.str)
}
}
关于SwiftUI:不同 View 之间的数据共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66595880/