web-dev-qa-db-fra.com

Obtenez des symboles monétaires à partir du code devise avec swift

Comment puis-je obtenir les symboles monétaires pour le code de devise correspondant avec Swift (macOS).

Exemple:

  • EUR = 1,00 €
  • USD = 1,00 $
  • CAD = 1,00 $
  • GBP = 1,00 £

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?

21
Geek20

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)
}
29
Pancho

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$"
11
Dave DeLong

La réponse peut être tardive mais j'espère que cela aidera à clarifier la cause profonde.

Problème

  • Le code de devise n'implique pas les paramètres régionaux et régionaux

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

Solution

De nombreuses applications varient, mais voici les étapes que j'ai suivies et qui me conviennent pour mon application:

  1. Rechercher des candidats de paramètres régionaux correspondants à l'aide de la recherche de code de devise à partir de tous les identificateurs de paramètres régionaux
  2. Choisissez le symbole le plus court parmi les candidats
  3. Stockez le symbole quelque part afin qu'il ne doive pas être calculé à chaque fois

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

  1. Instinctivement, je vois que l'approche du symbole à une lettre peut montrer un symbole incorrect s'il y a plus d'un symbole distinct pour le code de devise, mais je n'ai pas vu un tel cas.
  2. Le calcul à chaque fois est un travail lourd, donc lorsqu'un utilisateur définit son paramètre de devise, il est sage de stocker le résultat calculé et de l'utiliser à chaque recherche
9
tsuz

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) }
}
5
Gunhan
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) 
}
3
that guy

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;
}
3
mpatzer

Vous pouvez essayer ceci:

let formatter = NSNumberFormatter()

for locale in NSLocale.availableLocaleIdentifiers() {
    formatter.locale = NSLocale(localeIdentifier: locale)
    print("\(formatter.currencyCode) =  \(formatter.currencySymbol)")
}
1
MirekE

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)
}
1
Agent Smith

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)")
0
fs_tigre
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

0
iOS_Engineer