NumberFormatter 字符串作为次要货币单位而不是区域设置的主要单位(例如 99p 不是 £0.99)
NumberFormatter string as minor currency unit not major with locale (e.g 99p not £0.99)
我们使用此函数将 SKProduct 转换为消耗品包的每件商品的本地化价格:
static func pricePerUnit(_ product: SKProduct, quantity: NSDecimalNumber) -> String? {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
numberFormatter.locale = product.priceLocale
let pricePerItem = product.price.dividing(by: quantity)
guard let formattedPricePerItem = numberFormatter.string(from: pricePerItem) else {
return nil
}
return "\(formattedPricePerItem) each"
}
例如,10 件商品售价 9.99 英镑对于英国用户为 0.99 英镑,对于美国用户为 0.99 美元。
理想情况下,如果金额小于一个货币单位(又名一美元),我们希望它以次要货币单位(例如美分、便士等)显示。
我找不到这个或其他任何答案的 NumberFormatter 样式。这可以使用 NumberFormatter 完成吗?
遗憾的是,这无法使用 NumberFormatter
完成。 NumberFormatter
使用Locale
获取货币格式,包括小数位数、正码、负码、货币符号等
(参见 Number Format Patterns in Unicode)
但是,小货币的格式在 Unicode 中没有标准化(尽管一些必要的数据是,例如乘数)并且它不存在于 iOS Locale
数据中。
NumberFormatter
可能不直接支持分和便士的格式,但 NumberFormatter
足够灵活,您可以根据自己的意愿进行配置。例如,可以创建一个包含 2 NumberFormatter
的辅助结构:一个以美元和英镑的形式格式化,一个以分和便士的形式格式化。
struct CurrencyFormatter {
private static let defaultFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
return formatter
}()
private static let alternativeFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.multiplier = 100
return formatter
}()
static var alternativeCurrencySymbols = [
"USD": "c",
"GBP": "p"
]
static func string(from number: NSNumber, locale: Locale) -> String? {
var formatter = defaultFormatter
if number.isLessThan(1),
let currencyCode = locale.currencyCode,
let alternativeCurrencySymbol = alternativeCurrencySymbols[currencyCode]
{
formatter = alternativeFormatter
formatter.positiveSuffix = alternativeCurrencySymbol
formatter.negativeSuffix = alternativeCurrencySymbol
}
formatter.locale = locale
return formatter.string(from: number)
}
}
let number = NSNumber(value: 0.7)
let locale = Locale(identifier: "en_GB")
if let str = CurrencyFormatter.string(from: number, locale: locale) {
print(str) // result: 70p
}
该解决方案具有 built-in 故障保护机制。如果您没有为货币定义替代符号,它将回退到默认货币格式。您可以通过将语言环境更改为 fr_FR
来测试它,结果变为 0,70 €
.
我们使用此函数将 SKProduct 转换为消耗品包的每件商品的本地化价格:
static func pricePerUnit(_ product: SKProduct, quantity: NSDecimalNumber) -> String? {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
numberFormatter.locale = product.priceLocale
let pricePerItem = product.price.dividing(by: quantity)
guard let formattedPricePerItem = numberFormatter.string(from: pricePerItem) else {
return nil
}
return "\(formattedPricePerItem) each"
}
例如,10 件商品售价 9.99 英镑对于英国用户为 0.99 英镑,对于美国用户为 0.99 美元。
理想情况下,如果金额小于一个货币单位(又名一美元),我们希望它以次要货币单位(例如美分、便士等)显示。
我找不到这个或其他任何答案的 NumberFormatter 样式。这可以使用 NumberFormatter 完成吗?
遗憾的是,这无法使用 NumberFormatter
完成。 NumberFormatter
使用Locale
获取货币格式,包括小数位数、正码、负码、货币符号等
(参见 Number Format Patterns in Unicode)
但是,小货币的格式在 Unicode 中没有标准化(尽管一些必要的数据是,例如乘数)并且它不存在于 iOS Locale
数据中。
NumberFormatter
可能不直接支持分和便士的格式,但 NumberFormatter
足够灵活,您可以根据自己的意愿进行配置。例如,可以创建一个包含 2 NumberFormatter
的辅助结构:一个以美元和英镑的形式格式化,一个以分和便士的形式格式化。
struct CurrencyFormatter {
private static let defaultFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
return formatter
}()
private static let alternativeFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.multiplier = 100
return formatter
}()
static var alternativeCurrencySymbols = [
"USD": "c",
"GBP": "p"
]
static func string(from number: NSNumber, locale: Locale) -> String? {
var formatter = defaultFormatter
if number.isLessThan(1),
let currencyCode = locale.currencyCode,
let alternativeCurrencySymbol = alternativeCurrencySymbols[currencyCode]
{
formatter = alternativeFormatter
formatter.positiveSuffix = alternativeCurrencySymbol
formatter.negativeSuffix = alternativeCurrencySymbol
}
formatter.locale = locale
return formatter.string(from: number)
}
}
let number = NSNumber(value: 0.7)
let locale = Locale(identifier: "en_GB")
if let str = CurrencyFormatter.string(from: number, locale: locale) {
print(str) // result: 70p
}
该解决方案具有 built-in 故障保护机制。如果您没有为货币定义替代符号,它将回退到默认货币格式。您可以通过将语言环境更改为 fr_FR
来测试它,结果变为 0,70 €
.