感谢workingdog what 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 绑定,当该字段因点击返回或而失去焦点时选择另一个字段。如果现金格式化失败,闭包将首先尝试现金格式化或基本的双重格式化。