Pegasus
Pegasus

Reputation: 95

Getting NumberFormatter Currency by Country ISO

I have created a big list of country currencies and their ISO Code.

Example:

 "USD" - "United States"
 "EUR" - "Euro"
 "JPY" - "Yen"

A user selects their custom currency and I store it in UserDefaults.

In my number formatter how can I get the currency to show up by passing in the iso code?

I have something like this but it doesn't seem to work correctly.

 let formatter = NumberFormatter()

 let locale = Locale.availableIdentifiers.map { Locale(identifier: $0) }.first { $0.currencyCode == "EUR" }

// Instead of EUR I would display the user defaults. Testing Purposes Only.

 formatter.numberStyle = .currency
 formatter.locale  = locale as Locale
 formatter.maximumFractionDigits = 2
 $0.formatter = formatter

Upvotes: 1

Views: 1267

Answers (2)

rmaddy
rmaddy

Reputation: 318774

I have an app that does just what you are asking about. It lets a user select a specific currency code and then currency values can be formatted in the user's own locale but using the specific currency code.

What I do is create a custom locale identifier based on the user's own locale and the specific currency code. That custom locale is then used as the locale of a regular NumberFormatter setup for currency styling.

// Pull apart the components of the user's locale
var locComps = Locale.components(fromIdentifier: Locale.current.identifier)
// Set the specific currency code
locComps[NSLocale.Key.currencyCode.rawValue] = "JPY" // or any other specific currency code
// Get the updated locale identifier
let locId = Locale.identifier(fromComponents: locComps)
// Get the new custom locale
let loc = Locale(identifier: locId)

// Create a normal currency formatter using the custom locale
let currFmt = NumberFormatter()
currFmt.locale = loc
currFmt.numberStyle = .currency

This all assumes that you want the numbers to appear just as the current user would expect numbers to appear. The number formatting is not affected by selected currency code. Even the position of the currency symbol in the resulting output is not affected by the specific code.

A user in the USA would see currencies formatted something like:

$1,234.56
€1,234.56
¥1,235

while a user in Germany would see:

1.234,56 $
1.234,56 €
1.235 ¥

Upvotes: 5

ielyamani
ielyamani

Reputation: 18581

You could do something like this:

if let userLocaleName = UserDefaults.standard.string(forKey: "put here the string used to store the the locale"),
    !userLocaleName.isEmpty
{
    formatter.locale = Locale(identifier: userLocaleName)
}
//if the user locale is not set, revert to the default locale
else if let defaultLocaleName = Locale.availableIdentifiers.first(where: {Locale(identifier: $0).currencyCode == "EUR"})
{
    let defaultLocale = Locale(identifier: defaultLocaleName)
    formatter.locale = defaultLocale
} else {
    fatalError("Error setting the locale")
}

The if-let construct was used in the code above to avoid force unwrapping optional variables.

And then set the rest of the formatter properties:

formatter.numberStyle = .currency
formatter.maximumFractionDigits = 2

Upvotes: 0

Related Questions