Comment puis-je obtenir les symboles monétaires pour le code de devise correspondant avec Swift (macOS).
Exemple:
Mon code:
var formatter = NSNumberFormatter()
formatter.currencySymbol = getSymbol(currencyCode)
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
let number = NSNumber(double: (amount as NSString).doubleValue)
let amountWithSymbol = formatter.stringFromNumber(number)!
getSymbol(_ currencyCode: String) -> String
ou .. y a-t-il une meilleure façon?
Un peu en retard mais c'est une solution que j'ai utilisée pour obtenir le $ au lieu de US $ etc. pour le symbole monétaire.
/*
* Bear in mind not every currency have a corresponding symbol.
*
* EXAMPLE TABLE
*
* currency code | Country & Currency | Currency Symbol
*
* BGN | Bulgarian lev | лв
* HRK | Croatian Kuna | kn
* CZK | Czech Koruna | Kč
* EUR | EU Euro | €
* USD | US Dollar | $
* GBP | British Pound | £
*/
func getSymbol(forCurrencyCode code: String) -> String? {
let locale = NSLocale(localeIdentifier: code)
return locale.displayNameForKey(NSLocaleCurrencySymbol, value: code)
}
Fondamentalement, cela crée NSLocale
à partir de votre code de devise et récupère l'attribut d'affichage de la devise. Dans les cas où le résultat correspond au code de devise, par exemple SEK
, il créera de nouveaux paramètres régionaux spécifiques au pays en supprimant le dernier caractère du code de devise et en ajoutant "_en" au formulaire SE_en
. Ensuite, il essaiera à nouveau d'obtenir le symbole monétaire.
Swift 3 & 4
func getSymbol(forCurrencyCode code: String) -> String? {
let locale = NSLocale(localeIdentifier: code)
if locale.displayName(forKey: .currencySymbol, value: code) == code {
let newlocale = NSLocale(localeIdentifier: code.dropLast() + "_en")
return newlocale.displayName(forKey: .currencySymbol, value: code)
}
return locale.displayName(forKey: .currencySymbol, value: code)
}
La bonne façon de le faire est de laisser les cadres vous fournir les informations.
Vous pouvez récupérer ces informations à l'aide d'une méthode de classe obscure sur NSLocale
appelée localeIdentifierFromComponents()
. Cette méthode prendra un dictionnaire qui définit divers attributs de vos paramètres régionaux, puis retourne un identifiant que vous pouvez utiliser pour réellement construire une instance NSLocale
. Une fois que vous avez le NSLocale
, vous pouvez lui demander son CurrencySymbol
, comme ceci:
let currencyCode = "CAD"
let localeComponents = [NSLocaleCurrencyCode: currencyCode]
let localeIdentifier = NSLocale.localeIdentifierFromComponents(localeComponents)
let locale = NSLocale(localeIdentifier: localeIdentifier)
let currencySymbol = locale.objectForKey(NSLocaleCurrencySymbol) as! String
// currencySymbol is "CA$"
La réponse peut être tardive mais j'espère que cela aidera à clarifier la cause profonde.
La raison pour laquelle CAD devient CA $ est probablement parce que NSLocale
recherche le premier code de devise correspondant, et pour CAD, ce sont les localeIdentifiers
correspondants dans l'ordre de NSLocale.availableLocaleIdentifiers
1. Optional("CA$") Optional("CA") iu_CA
2. Optional("$") Optional("CA") fr_CA
3. Optional("$") Optional("CA") en_CA
iu_CA
est inuktitut mais je ne sais pas pourquoi il est répertorié comme CA$
, mais j'espère que le point est clair.
De même en CNY (yuan chinois):
1. Optional("CN¥") Optional("CN") en_CN
2. Optional("¥") Optional("CN") yue_CN
3. Optional("¥") Optional("CN") bo_CN
4. Optional("¥") Optional("CN") zh_CN
5. Optional("¥") Optional("CN") ug_CN
6. Optional("¥") Optional("CN") ii_CN
La raison pour laquelle afficher CN ¥ lorsque en_CN est probablement due au fait que JPY utilise également ¥.
En CHF (Franc Suisse), ils n'ont pas de symbole à une lettre:
1. Optional("CHF") Optional("LI") gsw_LI
2. Optional("CHF") Optional("CH") de_CH
...
9. Optional("CHF") Optional("CH") en_CH
10. Optional("CHF") Optional("CH") it_CH
De nombreuses applications varient, mais voici les étapes que j'ai suivies et qui me conviennent pour mon application:
Mise en œuvre
func getSymbolForCurrencyCode(code: String) -> String {
var candidates: [String] = []
let locales: [String] = NSLocale.availableLocaleIdentifiers
for localeID in locales {
guard let symbol = findMatchingSymbol(localeID: localeID, currencyCode: code) else {
continue
}
if symbol.count == 1 {
return symbol
}
candidates.append(symbol)
}
let sorted = sortAscByLength(list: candidates)
if sorted.count < 1 {
return ""
}
return sorted[0]
}
func findMatchingSymbol(localeID: String, currencyCode: String) -> String? {
let locale = Locale(identifier: localeID as String)
guard let code = locale.currencyCode else {
return nil
}
if code != currencyCode {
return nil
}
guard let symbol = locale.currencySymbol else {
return nil
}
return symbol
}
func sortAscByLength(list: [String]) -> [String] {
return list.sorted(by: { $0.count < $1.count })
}
tilisation
let usd = getSymbolForCurrencyCode(code: "USD")
let jpy = getSymbolForCurrencyCode(code: "JPY")
let cny = getSymbolForCurrencyCode(code: "CNY")
let cad = getSymbolForCurrencyCode(code: "CAD")
let uah = getSymbolForCurrencyCode(code: "UAH")
let krw = getSymbolForCurrencyCode(code: "KRW")
let zar = getSymbolForCurrencyCode(code: "ZAR")
let chf = getSymbolForCurrencyCode(code: "CHF")
let all = [usd, jpy, cny, cad, uah, krw, zar, chf]
(lldb) po all
▿ 8 elements
- 0 : "$"
- 1 : "¥"
- 2 : "¥"
- 3 : "$"
- 4 : "₴"
- 5 : "₩"
- 6 : "R"
- 7 : "CHF"
Problèmes
J'ai combiné et amélioré toutes les suggestions ici pour avoir une solution de dépôt (copier/coller) pour les futurs lecteurs (vous).
Il a son propre cache local, insensible à la casse, et possède une méthode d'extension pour assurer le chaînage de String
. Swift
4/5 prêt.
Comment utiliser:
"USD".currencySymbol //returns "$"
//OR
Currency.shared.findSymbol(currencyCode: "TRY") //returns "₺"
Tests:
XCTAssertEqual("$", "USD".currencySymbol)
XCTAssertEqual("₺", "TRY".currencySymbol)
XCTAssertEqual("€", "EUR".currencySymbol)
XCTAssertEqual("", "ASDF".currencySymbol)
Code:
class Currency {
static let shared: Currency = Currency()
private var cache: [String:String] = [:]
func findSymbol(currencyCode:String) -> String {
if let hit = cache[currencyCode] { return hit }
guard currencyCode.count < 4 else { return "" }
let symbol = findSymbolBy(currencyCode)
cache[currencyCode] = symbol
return symbol
}
private func findSymbolBy(_ currencyCode: String) -> String {
var candidates: [String] = []
let locales = NSLocale.availableLocaleIdentifiers
for localeId in locales {
guard let symbol = findSymbolBy(localeId, currencyCode) else { continue }
if symbol.count == 1 { return symbol }
candidates.append(symbol)
}
return candidates.sorted(by: { $0.count < $1.count }).first ?? ""
}
private func findSymbolBy(_ localeId: String, _ currencyCode: String) -> String? {
let locale = Locale(identifier: localeId)
return currencyCode.caseInsensitiveCompare(locale.currencyCode ?? "") == .orderedSame
? locale.currencySymbol : nil
}
}
extension String {
var currencySymbol: String { return Currency.shared.findSymbol(currencyCode: self) }
}
Swift4
//converting USD to $a and GBP to £
viewDidLoad()
{
print(getSymbolForCurrencyCode(code: "USD")!) // prints $
print(getSymbolForCurrencyCode(code: "GBP")!) //prints £
}
func getSymbolForCurrencyCode(code: String) -> String?
{
let locale = NSLocale(localeIdentifier: code)
return locale.displayName(forKey: NSLocale.Key.currencySymbol, value: code)
}
Une solution imparfaite que j'ai trouvée pour obtenir $
au lieu de US$
ou CA$
devait d'abord essayer de faire correspondre les paramètres régionaux actuels de l'utilisateur au code de devise. Cela fonctionnera dans les situations où vous créez une application mobile et où une API vous envoie un code de devise basé sur les paramètres du compte de cet utilisateur. Pour nous, l'analyse de rentabilisation est que 99% des utilisateurs ont le même code de devise défini dans leur compte sur le backend (USD
, CAD
, EUR
, etc.), où nous obtenons les informations, comme ils le font sur leur application mobile où nous affichons les devises de la façon dont un utilisateur s'attend à les voir (par exemple $50.56
au lieu de US$ 50.56
).
Objectif-C
- (NSLocale *)localeFromCurrencyCode:(NSString *)currencyCode {
NSLocale *locale = [NSLocale currentLocale];
if (![locale.currencyCode isEqualToString:currencyCode]) {
NSDictionary *localeInfo = @{NSLocaleCurrencyCode:currencyCode};
locale = [[NSLocale alloc] initWithLocaleIdentifier:[NSLocale localeIdentifierFromComponents:localeInfo]];
}
return locale;
}
rapide
func locale(from currencyCode: String) -> Locale {
var locale = Locale.current
if (locale.currencyCode != currencyCode) {
let identifier = NSLocale.localeIdentifier(fromComponents: [NSLocale.Key.currencyCode.rawValue: currencyCode])
locale = NSLocale(localeIdentifier: identifier) as Locale
}
return locale;
}
Vous pouvez essayer ceci:
let formatter = NSNumberFormatter()
for locale in NSLocale.availableLocaleIdentifiers() {
formatter.locale = NSLocale(localeIdentifier: locale)
print("\(formatter.currencyCode) = \(formatter.currencySymbol)")
}
Swift 4 Version de la réponse de Pancho, car String.characters est désormais obsolète.
Nous pouvons simplement appliquer dropLast () sur String.
func getCurrencySymbol(from currencyCode: String) -> String? {
let locale = NSLocale(localeIdentifier: currencyCode)
if locale.displayName(forKey: .currencySymbol, value: currencyCode) == currencyCode {
let newlocale = NSLocale(localeIdentifier: currencyCode.dropLast() + "_en")
return newlocale.displayName(forKey: .currencySymbol, value: currencyCode)
}
return locale.displayName(forKey: .currencySymbol, value: currencyCode)
}
Pour obtenir simplement le symbole monétaire dans Swift.
let locale = Locale.current // currency symbol from current location
//let locale = Locale(identifier: "fr_FR") // or you could specify the locale e.g fr_FR, en_US etc
let currencySymbol = locale.currencySymbol!
print("\(currencySymbol)")
let countryCode = (Locale.current as NSLocale).object(forKey: .currencySymbol) as? String ?? "$"
Ci-dessus donnera le symbole de la devise actuelle, pour le Royaume-Uni, il me donne = £ Apple Doc