答案可能会晚一些,但希望这有助于澄清根本原因。
问题
CAD变成CA$的原因可能是因为NSLocale
在查找第一个匹配的货币代码时,对于CAD而言,以下是按照NSLocale.availableLocaleIdentifiers
顺序排序的匹配的localeIdentifiers
:
1. Optional("CA$") Optional("CA") iu_CA
2. Optional("$") Optional("CA") fr_CA
3. Optional("$") Optional("CA") en_CA
iu_CA
是伊努克提图特语,但我不确定为什么它被列为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
在 en_CN 显示 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
解决方案
虽然应用程序各不相同,但这是我为自己的应用程序采取的步骤:
- 使用所有语言环境标识符的货币代码查找匹配的地区候选项
- 从候选项中选择最短的符号
- 将符号存储在某个地方,以便不需要每次重新计算
实现
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"
问题
- 本能地,我认为如果货币代码有多个不同的符号,则一个字母的符号方法可能会显示出错误的符号,但我没有见过这种情况。
- 每次计算都很耗费精力,因此当用户设置他们的货币设置时,明智的做法是存储计算结果并在每次查找时使用该结果。
NSLocale(localeIdentifier :)
的参数应该是一个本地标识符,通常由ISO 639-1语言代码(例如英语为en)和ISO 3166-2区域代码(例如美国为US)组成。但是在上面的代码中将货币代码传递给了该函数。这很奇怪。 - rayx