当您点击另一个TextField时,如何获取TextField的绑定值以进行更新?

时间:2020-04-09 13:20:44

标签: ios swiftui textfield

如果我使用以下命令创建一个SwiftUI文本字段:

init<S, T>(_ title: S, value: Binding<T>, formatter: Formatter)

仅在按下Return键时更新边界值。如果我在按回车键之前选择了另一个字段,则第一个字段仍会显示其新值,但绑定变量不会更新。

以下初始化似乎可以帮助onEditingChanged

init<S, T>(_ title: S, value: Binding<T>, formatter: Formatter, onEditingChanged: @escaping (Bool) -> Void = { _ in }, onCommit: @escaping () -> Void = {})

但是documentation目前实际上是空的。较早的question似乎很相似,但是没有公开的答案,可能早于上面的第二个初始化。

如果绑定值未更新,如何在OnCommit动作中抓取TextField中显示的字符串以设置其格式/将其转换为数字?

2 个答案:

答案 0 :(得分:2)

尝试这样的事情:

struct ContentView: View {

@State var test1 = "test1"
@State var test2 = "test2"

var body: some View {
    VStack {
        TextField(test1, text: Binding(get: {
            self.test1
        }, set: { newVal in
            self.test1 = newVal
            self.test2 = newVal
        }))
        TextField(test2, text: $test2)
    }
}

答案 1 :(得分:0)

感谢workingdogwhat was almost the answer.在格式化程序上无法正常运行,但它给了我一个可行的想法。

在绑定内部进行格式化不起作用,因为格式化后光标有时会跳来跳去。

首先是我的现金格式化程序:

let cashFormat = getCashFormat()
func getCashFormat() -> NumberFormatter {
    let thisCashFormat = NumberFormatter()
    thisCashFormat.numberStyle = NumberFormatter.Style.currency
    thisCashFormat.roundingMode = NumberFormatter.RoundingMode.halfEven
    // halfEven rounding is sometimes referred to as Bankers’ rounding.
    thisCashFormat.maximumFractionDigits = 2
    return thisCashFormat
}
如果字符串不以$作为第一个字符,

cashFormat格式将返回nil。我需要另一个NumberFormatter

let basicFormat = getBasicFormat()
func getBasicFormat() -> NumberFormatter {
    let thisBasicFormat = NumberFormatter()
    thisBasicFormat.numberStyle = NumberFormatter.Style.decimal
    thisBasicFormat.roundingMode = NumberFormatter.RoundingMode.halfEven
    thisBasicFormat.minimumFractionDigits = 0
    thisBasicFormat.maximumFractionDigits = 6
    return thisBasicFormat
}

basicFormat返回的小数位数超出了我的需要,但是在模型存储它之前,我将在我的应用程序中的其他位置将双精度整数转换为整数美分。

我为格式化创建了一个ObservableObject类。

class FieldFormatter: ObservableObject {
    @Binding var dollars: Double
    @Published var dollarText: String

    init(dollars: Binding<Double>) {
        self._dollars = dollars
        self.dollarText = dollars.wrappedValue.cash()
    }

    func dollarsChanged() {
        if let thisNumber = cashFormat.number(from: dollarText) {
            self.dollars = thisNumber.doubleValue
        } else if let thisNumber = basicFormat.number(from: dollarText) {
            self.dollars = thisNumber.doubleValue
        }
    }
}

最后,这是我的TextField结构。

struct CashFieldC: View {

    var thisLabel: String
    @Binding var dollars: Double
    @ObservedObject var fieldFormatter: FieldFormatter

    init(thisLabel: String, dollars: Binding<Double>) {
        self.thisLabel = thisLabel
        self._dollars = dollars
        self.fieldFormatter = FieldFormatter(dollars: dollars)
    }

    var body: some View {
        VStack(alignment: .leading) {
            Text(thisLabel).font(.caption)
            TextField(thisLabel, text: $fieldFormatter.dollarText, onEditingChanged: { (oec) in
                if !oec {
                    self.fieldFormatter.dollarsChanged()
                }
            })
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .keyboardType(.numbersAndPunctuation)
        }
    }
}

初始化dollarText对象时设置FieldFormatter值。每次输入字符时,TextField中的绑定都会对其进行更新。

格式化字段中的绑定变量仅在按回车键提交时才更新。

在接近工作犬答案的绑定中设置格式会导致光标在输入每个数字后跳来跳去。

当该字段失去焦点而不是在选择另一个字段时按回车时,此结构使用onEditingChanged:闭包来更新dollars绑定。如果现金格式化失败,则关闭将尝试首先进行现金格式化,或者尝试进行基本的双重格式化。