重用视图,而无需将绑定传递给每个中间视图

时间:2020-05-10 14:55:59

标签: view binding swiftui state reusability

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

简单的示例结构:

View1:

struct SwiftUIView3: View {

    @Binding var textInTextField: String

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

View2:

struct SwiftUIView2: View {

    @Binding var textInTextField: String

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

View3:

struct ContentView: View {

    @State private var textInTextField = ""

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

1 个答案:

答案 0 :(得分:0)

这是可能的解决方案。使用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
    }
 }