SwiftUI:不同视图之间的数据共享
SwiftUI: Data sharing between separate views
在视图之间共享变量的最佳做法是什么?
我的应用只有一个视图。但是随着它变得越来越复杂,我想我应该把它分成几个视图。还要分开方法。
我从这样的事情开始:
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。但是不要明白。提前感谢您的指点。
有很多方法可以解决这个问题。
我的选择可能是将绑定仅传递给您需要访问的变量。这可能看起来像这样:
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
中,有一个参数传递给每个子视图,包含到 GlobalVars
str
的绑定(使用 $
符号) 属性.
此外,doSomething
已移入 ControlView
的体内
您也可以使用 EnvironmentObject 来处理这个问题。我个人不太喜欢这种方法,因为我更愿意明确地查看参数的去向。它还为子视图提供了对整个 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
的视图层次结构中传递给子级。每个子视图都可以通过声明 @EnvironmentObject var globalvars : GlobalVars
的 属性 来访问它
您还可以做一种混合模型,在该模型中您将 ObservableObject 作为参数显式传递给子视图:
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)
}
}
在视图之间共享变量的最佳做法是什么? 我的应用只有一个视图。但是随着它变得越来越复杂,我想我应该把它分成几个视图。还要分开方法。 我从这样的事情开始:
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。但是不要明白。提前感谢您的指点。
有很多方法可以解决这个问题。
我的选择可能是将绑定仅传递给您需要访问的变量。这可能看起来像这样:
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
中,有一个参数传递给每个子视图,包含到 GlobalVars
str
的绑定(使用 $
符号) 属性.
此外,doSomething
已移入 ControlView
您也可以使用 EnvironmentObject 来处理这个问题。我个人不太喜欢这种方法,因为我更愿意明确地查看参数的去向。它还为子视图提供了对整个 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
的视图层次结构中传递给子级。每个子视图都可以通过声明 @EnvironmentObject var globalvars : GlobalVars
您还可以做一种混合模型,在该模型中您将 ObservableObject 作为参数显式传递给子视图:
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)
}
}