NumberFormatter字符串作为次要货币单位不是主要的区域设置(例如99p不是£0.99)

时间:2018-03-14 15:48:58

标签: ios swift nsnumberformatter

我们使用此功能将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美元。

理想情况下,如果金额小于单位货币(也就是1美元),我们希望它以次要货币单位显示(例如美分,便士等)。

我找不到这个或其他地方的任何答案的NumberFormatter风格。可以使用NumberFormatter完成吗?

2 个答案:

答案 0 :(得分:1)

不幸的是,使用NumberFormatter无法做到这一点。 NumberFormatter使用Locale获取货币格式,包括小数位数,正模式,负数模式,货币符号等。

(见Number Format Patterns in Unicode

但是,小型货币的格式在Unicode中没有标准化(尽管一些必要的数据是例如乘数),并且它在iOS Locale数据中不存在。

答案 1 :(得分:1)

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
}

该解决方案具有内置的故障安全机制。如果您还没有为货币定义替代符号,它将回退到默认货币格式。您可以通过将区域设置更改为fr_FR来对其进行测试,结果将变为0,70 €