0

I want to format a Double value such as -24.5 into a currency formatted string like -$24.50. How would I do that in Swift?

I followed this post, but it ends up formatting as $-24.50 (negative sign after the $), which is not what I want.

Is there a more elegant solution to achieve this, besides something like this?

if value < 0 {
    return String(format: "-$%.02f", -value)
} else {
    return String(format: "$%.02f", value)
}
Octocat
  • 571
  • 2
  • 6
  • 20
  • 3
    NumberFormatter. I really strongly advise against using `String(format:)` in Swift in general, let alone for currency formatting. For one, there are currencies that don't use `$`, and there are locals which don't use a `.` as the decimal separator (e.g. `$1,234,567.89` might be `€1.234.567,89` in Europe) – Alexander Dec 31 '17 at 02:25

1 Answers1

4

Use NumberFormatter:

import Foundation

extension Double {
    var formattedAsLocalCurrency: String {
        let currencyFormatter = NumberFormatter()
        currencyFormatter.usesGroupingSeparator = true
        currencyFormatter.numberStyle = .currency
        currencyFormatter.locale = Locale.current
        return currencyFormatter.string(from: NSNumber(value: self))!
    }
}

print(0.01.formattedAsLocalCurrency) // => $0.01
print(0.12.formattedAsLocalCurrency) // => $0.12
print(1.23.formattedAsLocalCurrency) // => $1.23
print(12.34.formattedAsLocalCurrency) // => $12.34
print(123.45.formattedAsLocalCurrency) // => $123.45
print(1234.56.formattedAsLocalCurrency) // => $1,234.56
print((-1234.56).formattedAsLocalCurrency) // => -$1,234.56
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Question for the masses: Why does [`NumberFormatter.string(from:)`](https://developer.apple.com/documentation/foundation/numberformatter/1418046-string) return an optional? When can it fail? – Alexander Dec 31 '17 at 02:55
  • It is strange since `localizedString` does not return an optional. – rmaddy Dec 31 '17 at 04:31
  • Not sure, what happens when you pass an `NSNumber(bool: true)`? But he inconsistency with `localizedString` is weird. – HAS Dec 31 '17 at 08:48
  • @HAS It's actually `NSNumber(value:)`, even for `Bool`, and it just gets treated as 1.0 – Alexander Dec 31 '17 at 17:19
  • Sorry, wasn’t in front of a computer, thanks for checking! – HAS Dec 31 '17 at 18:27
  • Creating `NumberFormatter` instances are expensive like date formatters, etc. Better to cache the formatter into a private static variable. – TruMan1 Oct 02 '20 at 11:32
  • @TruMan1 Yeah, you're right. Though I'm not sure if there's a one-size-fits-all suggestion I could make for where to store the cached instance – Alexander Oct 02 '20 at 12:58