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

问题描述 投票:0回答:1

在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)
        }
    }
 }
view binding swiftui state reusability
1个回答
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
    }
 }

© www.soinside.com 2019 - 2024. All rights reserved.