Link @Binding to @Published with SwiftUI

Link @Binding to @Published with SwiftUI

我正在尝试弄清楚如何 link 传递到自定义视图中的 @Binding 到该视图模型中的 @Published。本质上,我正在尝试创建一个仅可重复使用的整数 TextField。我正在使用下面的代码,它可以将整数值设置到文本字段中,但我不知道如何在文本更改时更新绑定。

private class IntegerTextFieldValue: ObservableObject {
    @Published var value = "" {
        didSet {
            let numbersOnly = value.filter { [=11=].isNumber }
            if value != numbersOnly {
                value = numbersOnly
            }
        }
    }
}

struct IntegerTextField: View {
    @Binding var value: Int?
    @StateObject private var fieldValue = IntegerTextFieldValue()

    var placeholder = ""

    var body: some View {
        TextField(placeholder, text: $fieldValue.value)
            .keyboardType(.numberPad)
            .onAppear {
                if let value = value {
                    fieldValue.value = "\(value)"
                }
            }
    }
}

如果我没理解错的话

.onChange (of: fieldValue.value) { vl in
    value = vl
}

此修饰符将绑定 value 更新为 $fieldValue.value

这里是用于演示可能方法的修改代码(使用 Xcode 12.1 / iOS 14.1 测试):

private class IntegerTextFieldValue: ObservableObject {
    @Published var value = "" {
        didSet {
            let numbersOnly = value.filter { [=10=].isNumber }
            if value != numbersOnly {
                value = numbersOnly
            }

            if let number = Int(value) {
                numberValue = number
            }
        }
    }
    
    @Published var numberValue: Int = 0
}

struct IntegerTextField: View {
    @Binding var value: Int?
    @StateObject private var fieldValue = IntegerTextFieldValue()

    var placeholder = ""

    var body: some View {
        TextField(placeholder, text: $fieldValue.value)
            .keyboardType(.numberPad)
            .onAppear {
                if let value = value {
                    fieldValue.value = "\(value)"
                }
            }
            .onChange(of: fieldValue.numberValue) {
                if [=10=] != self.value {
                    self.value = [=10=]
                }
            }
    }
}