gpt4 book ai didi

swift - 如何让用户在 SwiftUI 文本字段中仅使用数字输入货币,同时保留 $ 和 .?

转载 作者:行者123 更新时间:2023-12-05 01:08:42 40 4
gpt4 key购买 nike

现在,我有以下内容:

private var currencyFormatter: NumberFormatter = {
let f = NumberFormatter()
// allow no currency symbol, extra digits, etc
f.isLenient = true
f.numberStyle = .currency
return f
}()

TextField("Total", value: $totalInput, formatter: currencyFormatter)
.font(.largeTitle)
.padding()
.background(Color.white)
.foregroundColor(Color.black)
.multilineTextAlignment(.center)

我希望文本字段以 $0.00 作为占位符开始,但是当用户开始输入时,前两个输入将以美分填充...所以 5055 将逐渐显示为:

Step 1 (user hits 5): $0.05
Step 2 (user hits 0): $0.50
Step 3 (user hits 5): $5.05
Step 4 (user hits 5): $50.55

如果金额大于 999 美元,则会插入逗号。

如何做到这一点?现在我的 totalInput 类型是 Double?。

最佳答案

要创建一个允许用户从右到左输入金额的货币字段,您需要一个可观察对象(绑定(bind)管理器)、一个货币数字格式化程序,并使用 onChange 方法观察每次值发生变化时:

import SwiftUI

struct ContentView: View {
@ObservedObject private var currencyManager = CurrencyManager(amount: 0)
@ObservedObject private var currencyManagerUS = CurrencyManager(
amount: 0,
locale: .init(identifier: "en_US")
)
@ObservedObject private var currencyManagerUK = CurrencyManager(
amount: 0,
locale: .init(identifier: "en_UK")
)
@ObservedObject private var currencyManagerFR = CurrencyManager(
amount: 0,
locale: .init(identifier: "fr_FR")
)
@ObservedObject private var currencyManagerBR = CurrencyManager(
amount: 100,
maximum: 100,
locale: .init(identifier: "pt_BR")
)
var body: some View {
VStack(alignment: .trailing, spacing: 0) {
Spacer()
Group {
Text("Locale currency")
TextField(currencyManager.string, text: $currencyManager.string)
.keyboardType(.numberPad)
.multilineTextAlignment(.trailing)
.onChange(of: currencyManager.string, perform: currencyManager.valueChanged)
Spacer()
}
Group {
Text("American currency")
TextField(currencyManagerUS.string, text: $currencyManagerUS.string)
.keyboardType(.numberPad)
.multilineTextAlignment(.trailing)
.onChange(of: currencyManagerUS.string, perform: currencyManagerUS.valueChanged)
Spacer()
}
Group {
Text("British currency")
TextField(currencyManagerUK.string, text: $currencyManagerUK.string)
.keyboardType(.numberPad)
.multilineTextAlignment(.trailing)
.onChange(of: currencyManagerUK.string, perform: currencyManagerUK.valueChanged)
Spacer()
}
Group {
Text("French currency")
TextField(currencyManagerFR.string, text: $currencyManagerFR.string)
.keyboardType(.numberPad)
.multilineTextAlignment(.trailing)
.onChange(of: currencyManagerFR.string, perform: currencyManagerFR.valueChanged)
Spacer()
}
Group {
Text("Brazilian currency")
TextField(currencyManagerBR.string, text: $currencyManagerBR.string)
.keyboardType(.numberPad)
.multilineTextAlignment(.trailing)
.onChange(of: currencyManagerBR.string, perform: currencyManagerBR.valueChanged)

}
Spacer()
}.padding(.trailing, 25)
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

class CurrencyManager: ObservableObject {

@Published var string: String = ""
private var amount: Decimal = .zero
private let formatter = NumberFormatter(numberStyle: .currency)
private var maximum: Decimal = 999_999_999.99
private var lastValue: String = ""

init(amount: Decimal, maximum: Decimal = 999_999_999.99, locale: Locale = .current) {
formatter.locale = locale
self.string = formatter.string(for: amount) ?? "$0.00"
self.lastValue = string
self.amount = amount
self.maximum = maximum
}

func valueChanged(_ value: String) {
let newValue = (value.decimal ?? .zero) / pow(10, formatter.maximumFractionDigits)
if newValue > maximum {
string = lastValue
} else {
string = formatter.string(for: newValue) ?? "$0.00"
lastValue = string
}
}
}

extension NumberFormatter {

convenience init(numberStyle: Style, locale: Locale = .current) {
self.init()
self.locale = locale
self.numberStyle = numberStyle
}
}

extension Character {

var isDigit: Bool { "0"..."9" ~= self }
}

extension LosslessStringConvertible {

var string: String { .init(self) }
}

extension StringProtocol where Self: RangeReplaceableCollection {

var digits: Self { filter (\.isDigit) }

var decimal: Decimal? { Decimal(string: digits.string) }
}

这是相当于自定义 CurrencyField 的 SwiftUI我已经为 UIKit 实现了。

关于swift - 如何让用户在 SwiftUI 文本字段中仅使用数字输入货币,同时保留 $ 和 .?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65783004/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com