[英]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
}
}
並想 go 那里:
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
您還可以做一種混合 model ,其中您將 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)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.