Search code examples
iosswiftcurrencynumberformatter

Swift NumberFormatter appends Unicode spaces to currency strings even when the currency symbol is blank


In iOS 13 it appears that in certain Locales, NumberFormatter appends a Unicode NO-BREAK SPACE or NARROW NO-BREAK SPACE to a string representation of the number, even when NumberFormatter's currencySymbol property is set to "" (blank).

Here's an example of this:

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
numberFormatter.currencySymbol = ""
numberFormatter.locale = Locale(identifier: "uk_US (current)")
let numberString = numberFormatter.string(from: NSNumber(value: 1))!
print ("-->\(numberString)<--")

Does anyone know a way of suppressing that appended space, short of having to filter it out of every converted string in other code?


Solution

  • You can set your own positive and negative formats to avoid such cases. Note that you should always set the locale before setting the formats and there is no need to initialize a NSNumber object from your value, you can use Formatter's string(for:) method:

    let numberFormatter = NumberFormatter()
    numberFormatter.locale = Locale(identifier: "uk_US")
    numberFormatter.numberStyle = .currency
    numberFormatter.positiveFormat = "##0.00"
    numberFormatter.negativeFormat = "-##0.00"
    let value: Double = 1
    let numberString = numberFormatter.string(for: value) ?? ""   // "1,00"
    print ("-->\(numberString)<--") // "-->1,00<--\n"
    

    For locales where there might not have fraction digits:

    let numberFormatter = NumberFormatter()
    // numberFormatter.locale = Locale(identifier: "ja_JP")
    numberFormatter.numberStyle = .currency
    let digits = numberFormatter.minimumFractionDigits
    let zeros = digits == 0 ? "" : "." + String(repeating: "0", count: digits)
    numberFormatter.positiveFormat = "##0" + zeros
    numberFormatter.negativeFormat = "-##0" + zeros
    let value: Double = 1
    let numberString = numberFormatter.string(for: value) ?? ""   // "1"
    print ("-->\(numberString)<--") // "-->1<--\n"