Получить символы валюты из кода валюты с быстрым

Как я могу получить символы валюты для соответствующего кода валюты с помощью Swift (macOS).

Пример:

  • EUR = 1,00 евро
  • USD = 1,00 доллара США
  • CAD = 1,00 доллара США
  • GBP = £ 1,00

Мой код:

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

или.. есть ли лучший способ?

Ответ 1

Немного поздно, но это решение, которое я использовал, чтобы получить $ вместо US $ и т.д. Для символа валюты.

/*
 * 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)
}

В основном это создает NSLocale из вашего кода валюты и захватывает атрибут отображения для валюты. В случае, когда результат соответствует коду валюты, например SEK он создаст новый языковой стандарт страны, удалив последний символ из кода валюты и добавив "_en" к форме SE_en. Затем он попытается снова получить символ валюты.

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

Ответ 2

Правильный способ сделать это - предоставить фреймворкам информацию для вас.

Вы можете получить эту информацию с помощью метода неясного класса на NSLocale, который называется localeIdentifierFromComponents(). Этот метод примет словарь, который определяет различные атрибуты вашей локали, а затем возвращает идентификатор, который вы можете использовать для фактического создания экземпляра NSLocale. Если у вас есть NSLocale, вы можете запросить его CurrencySymbol, например:

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$"

Ответ 3

Ответ может быть запоздалым, но, надеюсь, это поможет прояснить первопричину.

проблема

  • Код валюты не означает, что регион и регион

Причина, по которой CAD становится CA $, вероятно, NSLocale тем, что NSLocale просматривает первый соответствующий валютный код, а для CAD - соответствующие localeIdentifiers в порядке NSLocale.availableLocaleIdentifiers

1. Optional("CA$") Optional("CA") iu_CA
2. Optional("$") Optional("CA") fr_CA
3. Optional("$") Optional("CA") en_CA

iu_CA - Inuktitut, но я не уверен, почему он указан как CA$, но я надеюсь, что это ясно.

Аналогичным образом в CNY (китайский юань):

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

Причина появления CN ¥, когда en_CN, вероятно, связана с тем, что JPY также использует ¥.

В CHF (швейцарский франк) у них нет однобуквенного символа:

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

Решение

Многие приложения меняются, но это те шаги, которые я принял, что я доволен своим приложением:

  1. Найти подходящих кандидатов локали, используя поиск кодов валют из всех идентификаторов локали
  2. Выберите самый короткий символ из кандидатов
  3. Храните символ где-нибудь, чтобы он не приходилось вычислять каждый раз

Реализация

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

использование

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"

Проблемы

  1. Инстинктивно, я вижу, что подход с символом одной буквы может показывать неправильный символ, если для кода валюты имеется более одного символа, но такого случая я не видел.
  2. Вычисление это каждый раз тяжело поднимается, поэтому, когда пользователь устанавливает свой валютный настрой, разумно хранить вычисленный результат и использовать этот результат при каждом поиске

Ответ 4

Решение несовершенное, которое я обнаружил, чтобы получить $ вместо US$ или CA$, было попыткой сначала сопоставить текущую локаль пользователя с кодом валюты. Это будет работать в ситуациях, когда вы создаете мобильное приложение, а API отправляет вам код валюты на основе настроек в этой учетной записи пользователя. Для нас дело в том, что 99% пользователей имеют одинаковый код валюты, указанный в их учетной записи на бэкэнд (USD, CAD, EUR и т.д.), Откуда мы получаем информацию, так как они делают в своем мобильном приложении, где мы показываем валюту так, как пользователь ожидал бы ее увидеть (т.е. $50.56 вместо US$ 50.56).

Objective-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;
}

Swift

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

Ответ 5

Вы можете попробовать следующее:

let formatter = NSNumberFormatter()

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

Ответ 6

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

Ответ 7

Swift 4 Version ответа Pancho, так как теперь String.characters устарели.

Мы можем просто применить dropLast() к 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)
}

Ответ 8

Swift 4.2

// Currency Codes
Locale.isoCurrencyCodes

// Validation
let currencyCode = "USD"
let isValid = 0 < Locale.isoCurrencyCodes.filter { $0 == currencyCode }.count