Как получить привязанное значение TextField для обновления при нажатии другого TextField? - PullRequest
1 голос
/ 09 апреля 2020

Если я создаю SwiftUI TextField со следующим:

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

, он обновляет привязанное значение только при нажатии Return. Если я выберу другое поле перед нажатием возврата, то в первом поле все еще будет отображаться новое значение, но связанная переменная не обновляется.

Следующий init выглядит так, как будто onEditingChanged может помочь,

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

Но документация в настоящее время практически пуста. Этот ранний вопрос кажется похожим, но не имеет опубликованных ответов и может предшествовать второму описанному выше процессу init.

Если значение привязки не обновлено, в действии OnCommit как получить строка, отображаемая в TextField для ее форматирования / преобразования в число?

Ответы [ 2 ]

2 голосов
/ 09 апреля 2020

попробуйте что-то вроде этого:

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)
    }
}
0 голосов
/ 11 апреля 2020

Спасибо workingdog за , что было почти ответом. Это не сработало с форматером, но дало мне идею, что сработало.

Форматирование прямо внутри привязки не работает, потому что курсор иногда перепрыгивает после форматирования.

Сначала форматирование моего ca sh:

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 вернет ноль, если строка не имеет $ в качестве первого символа. Мне нужен еще один 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 обновляет его каждый раз, когда вводится символ.

Переменная, связанная в поле форматирования, обновляется только тогда, когда поле фиксируется при нажатии возврата.

Форматирование внутри Привязка близко к ответу Workingdog заставит курсор перескочить после ввода каждого di git.

Эта структура использует закрытие onEditingChanged: для обновления привязки dollars, когда поле теряет фокус из-за нажатия возврата или при выборе другого поля. Закрытие попытается сначала выполнить форматирование ca sh или двойное форматирование basi c, если форматирование ca sh завершится неудачей.

...