重用视图而不将绑定传递给每个中间视图

Reuse views without passing bindings to every intermediate view

在 swiftUI 中,创建一次性视图相当简单,其相应的状态嵌入到关联的视图模型中。但是我怎样才能使用例如view1 的自定义文本字段,嵌入在更复杂的 view2 中,在 view3 中哪个是最终视图?我知道我可以将 view1 的文本字段文本作为绑定传递给 view2,然后再传递给 view3。但是一旦 UI 变得复杂,就需要传递大量绑定,尤其是在存在大量中间视图的情况下。我如何在不将 view1 的文本字段文本状态传递给每个中间视图的情况下重用它,以及如何将其理想地实现到 view3 的视图模型中?

简单示例结构:

视图 1:

struct SwiftUIView3: View {

    @Binding var textInTextField: String

    var body: some View {
        TextField("Test", text: $textInTextField)
    }
}

视图 2:

struct SwiftUIView2: View {

    @Binding var textInTextField: String

    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 15)
                .frame(height: 200)
                .foregroundColor(.blue)
            SwiftUIView3(textInTextField: $textInTextField)
        }
    }
}

视图 3:

struct ContentView: View {

    @State private var textInTextField = ""

    var body: some View {
        VStack {
            SwiftUIView2(textInTextField: $textInTextField)
            Text(textInTextField)
        }
    }
 }

这是可能的解决方案。使用 Xcode 11.4 / iOS 13.4

测试

想法是使用视图模型作为环境对象注入到子层次结构中,因此在任何级别的子视图中都可以提取它并使用,顶层视图将相应地更新`因为它持有观察到的视图模型对象。

struct SwiftUIView3: View {
    @EnvironmentObject var eo: TextViewModel  //  << auto-associated

    var body: some View {
        TextField("Test", text: $eo.textInTextField)
    }
}

struct SwiftUIView2: View {
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 15)
                .frame(height: 200)
                .foregroundColor(.blue)
            SwiftUIView3()       //   << nothing to pass
        }
    }
}

class TextViewModel: ObservableObject {
    @Published var textInTextField = ""
}

struct ContentView: View {
    @ObservedObject private var vm = TextViewModel()

    var body: some View {
        VStack {
            SwiftUIView2()       //  << nothing to pass
            Text(vm.textInTextField)
        }.environmentObject(vm)      // << inject into hierarchy
    }
 }