Search code examples
ioscocoanumber-formattingfoundationnsnumberformatter

Currency NumberFormatter - omit fraction part when the number is integer


I need a specific behaviour from my NumberFormatter used to output currency:

  • If the number is integer (0, 0.00) it should not show decimal separator (0 €)
  • Else (123.90, 12.1), it should show two digits after decimal separator (123.90 €, 12.10 €).

The way I create and use my formatter now is the following:

let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencySymbol = "€"
formatter.alwaysShowsDecimalSeparator = false
let num = formatter.string(from: 123.9)!

If created like this, the formatter always shows decimal separator, despite the fact that I set this property to false.

How can I achieve this?


Solution

  • Currency numberStyle is always returning decimal point followed two digits. So if you want to achieve your goal, you should modify the output string by yourself.

    Please check the example code:

        let number1: Double = 123.908392857
        let number2: Int = 123
        let number3: Float = 123.00
    
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.currencySymbol = "€"
        let num1 = formatter.string(from: NSNumber(value: number1))! // Output €123.91
        let num2 = formatter.string(from: NSNumber(value: number2))! // Output €123.00
        let num3 = formatter.string(from: NSNumber(value: number3))! // Output €123.00
    
        print("\(num1) \(num2) \(num3)")
    
        // This is trick
        let newNum1 = trimString(string: num1) // Output €123.91
        let newNum2 = trimString(string: num2) // Output €123
        let newNum3 = trimString(string: num3) // Output €123
    
        print("\(newNum1) \(newNum2) \(newNum3)")
    

    trimString is a simple trim function, you can put it in the String extension or any place you want.

    func trimString(string: String) -> String {
        if string.hasSuffix(".00") {
            return String(string.dropLast(3))
        }
        else {
            return string
        }
    }
    

    You may have question about why alwaysShowsDecimalSeparator is not working then? It is for .decimal numberStyle and default decimalSeparator is "."