I am trying to make a simple TextField in SwiftUI that will format provided values as valid value for currency. I need to round the value to 2 digits. And store the rounded value using Core Data (this I know how to do, I am using Decimal type, BTW).
So far I have this:
import SwiftUI
struct ContentView: View {
@State private var newValueAsString = ""
@State private var value: NSDecimalNumber = 0
let decimalBehavior = NSDecimalNumberHandler(roundingMode: .plain, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
var body: some View {
VStack {
TextField("0", text: $newValueAsString, onCommit: {
self.value = NSDecimalNumber(string: self.newValueAsString).rounding(accordingToBehavior: self.decimalBehavior)
print("\(self.value)")
}
)
.multilineTextAlignment(.trailing)
.font(Font.system(size: 30))
.keyboardType(.decimalPad)
// Just to test. Later I will save the value to Core Data.
Text("\(self.value)")
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
THE PROBLEM
It doesn't work properly when iOS region uses commas instead of dots (for example, Poland). Decimal keyboard has "," not "." and when I use "," numbers are not rounded properly. 123,456 becomes 123. And with regions using dots (for example, USA) 123.456 becomes 123.46 as expected.
What am I missing here? My guess is NumberFormatter, but I cannot manage to make it work.
NSDecimalNumber
can be initialized with a string & locale.
The documentation explicitly mentions that locale is used for interpreting the decimal separator (emphasis mine):
locale : A dictionary (!) that defines the locale (specifically the decimalSeparator) to use to interpret the number in numericString.
So you could do something like:
// Here I am passing the current Locale but you should pass whatever makes sense to your input
self.value = NSDecimalNumber(string: self.newValueAsString, locale: Locale.current).rounding(accordingToBehavior: self.decimalBehavior)
Example:
print(NSDecimalNumber(string: "100.50", locale: Locale(identifier: "en_US"))) // => 100.5
print(NSDecimalNumber(string: "100,50", locale: Locale(identifier: "el_GR"))) // => 100.5