Swift UI - 提取到子视图 - 取决于 StateObject

时间:2021-07-24 11:33:31

标签: ios swift swiftui

我正在做我的第一个 Swift UI 项目。我有一个由视图模型 (vm: SectionFormViewModel) 支持的表单。我找到了一个巧妙的解决方案来限制此 SO answer 中的数字输入。

struct SectionForm: View {

    // @ObservedObject var homeVM: HomeViewModel

    @StateObject var vm = SectionFormViewModel()

    var body: some View {
        // ....
    }

    var roomVolume: some View {
        Section(header: Text("Room Dimensions")) {
            if vm.manualArea {
                HStack {

                    // Required to extract to component
                    // --------------------------------

                    TextField("Length (feet)", text: $vm.length)
                        //.keyboardType(.numberPad)
                        .onReceive(Just(vm.length)) { newValue in
                            let filtered = newValue.filter { "0123456789".contains($0) }
                            if filtered != newValue {
                                vm.length = filtered
                            }
                        }

我的想法是创建自己的 NumberField。它会被这样调用:

NumberField(label: "Length (feet)", binding: $vm.length)

但我不知道具体是怎么做的。

struct NumberField: View {
    @Binding var binding: Binding<String>
    
    var body: some View {
        TextField("Length (feet)", text: binding)
            //.keyboardType(.numberPad)
            .onReceive(Just($binding.wrappedValue)) { newValue in
                let filtered = newValue.filter { "0123456789".contains($0) }
                if filtered != newValue {
                    $binding.length = filtered
                }
            }
    }
}

首先,有没有可能做这样的事情?

我不认为它可以是 @State,因为它是在别处定义的。我认为它应该是一个 @Binding。这可能是显而易见的事情,但经过多次搜索、数小时磨牙、咬指甲和发际线后退,我相信我需要一些帮助。

对不起,标题,我什至不知道如何措辞。我是 Swift 的新手!

1 个答案:

答案 0 :(得分:1)

问题是,您已经创建了绑定的绑定。这是错误的。 看到你的代码。有两个绑定。

 @Binding var binding: Binding<String>

你的建筑应该是这样的。

struct NumberField: View {
    var label: String
    @Binding var binding: String
    
    var body: some View {
        TextField("Length (feet)", text: $binding)
            //.keyboardType(.numberPad)
            .onReceive(Just(binding)) { newValue in
                let filtered = newValue.filter { "0123456789".contains($0) }
                if filtered != newValue {
                    binding = filtered
                }
            }
    }
}

现在你可以这样使用它

NumberField(label: "Length (feet)", binding: $vm.length)