让我说我有这样的事情:
extension NSNumber{
func toLocalCurrency(fractDigits:Int = 2)->String{
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
let userSettings:UserInfo? = UserInfo.first(sortDescriptors: nil, context: AERecord.defaultContext) as? UserInfo
if let code = userSettings?.currency.name_short {
formatter.currencyCode = code
}
formatter.maximumFractionDigits = fractDigits
return formatter.stringFromNumber(self)!
}
func toLocalCurrencyWithoutFractionDigits()->String{
return self.toLocalCurrency(fractDigits: 0)
}
}
我希望尽可能支持大多数swift / mac数字类型,例如。 CGFLoat NSNumber Int Float等。但我不想重复自己(复制粘贴并扩展所有内容)或在我想要使用该功能的任何地方投射。
我尝试扩展像FloatLiteralType / Convertible这样的协议,但还需要强制转换。 “应该”可以以更方便的方式扩展基本类型。
我还想到了全局功能,但它们不易被发现并且感觉更加黑客。
有没有一种很好的方法可以在swift中实现这一目标?
答案 0 :(得分:9)
正如Sogmeister
已经说过你必须使用Swift 2.0来解决你的问题。
然后你可以这样做:
// the solution right now is to implement it twice, I'll explain why
extension IntegerType {
func toLocalCurrency(fractDigits:Int = 2) -> String {
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
/* ... */
formatter.maximumFractionDigits = fractDigits
return formatter.stringFromNumber(self as! NSNumber)! // probably like this
}
func toLocalCurrencyWithoutFractionDigits() -> String {
return self.toLocalCurrency(0)
}
}
extension FloatingPointType {
// second implementation goes here
}
// some example
let someUInt = UInt(12340)
someUInt.toLocalCurrency() // returns "12.340,00 €" for me
更新回答:
基本思路是使用函数的默认实现扩展MyProtocol
,然后扩展IntegerType
和FloatingPointType
。但这不会发生在Swift 2.0(see here)中。它之所以不起作用的原因是here。这是另一个解决方案,它比我的第一个更好。
protocol MyProtocol {}
extension MyProtocol {
func toLocalCurrency(fractDigits:Int = 2) -> String {
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
/* ... */
formatter.maximumFractionDigits = fractDigits
guard let newNumber = self as? NSNumber else { fatalError("this type is not convertable to NSNumber") }
return formatter.stringFromNumber(newNumber)!
}
func toLocalCurrencyWithoutFractionDigits() -> String {
return self.toLocalCurrency(0)
}
}
/* extend your number types you need */
extension Int : MyProtocol {}
extension Double : MyProtocol {} // done
答案 1 :(得分:2)
我们可以创建一个协议,使用默认实现对其进行扩展,并使我们所有的数字类型都符合该协议:
protocol FormattableNumeric {}
extension FormattableNumeric {
var localized: String {
guard let number = self as? NSNumber else { return "NaN" }
return number.description(withLocale: Locale.current)
}
}
extension Int: FormattableNumeric {}
extension UInt: FormattableNumeric {}
extension Float: FormattableNumeric {}
extension Double: FormattableNumeric {}
// etc.
根据当前的语言环境,您现在可以这样获得格式化的数字:
1000.localized // "1,000"
12_345_678.localized // "12,345,678"
(1_000_000 * Double.pi).localized // "3,141,592.65358979"
当然,为了更好地控制格式,我们还可以在实现中使用NumberFormatter
:
return NumberFormatter.localizedString(from: number, number: .decimal)
答案 2 :(得分:-1)
extension NSNumber {
func toLocalCurrency(fractDigits: Int = 2) -> String? {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.maximumFractionDigits = fractDigits
return formatter.string(from: self)
}
func toLocalCurrencyWithoutFractionDigits() -> String? {
return toLocalCurrency(fractDigits: 0)
}
}
extension Numeric {
func toLocalCurrency(fractDigits: Int = 2) -> String? {
return (self as? NSNumber)?.toLocalCurrency(fractDigits: fractDigits)
}
func toLocalCurrencyWithoutFractionDigits() -> String? {
return toLocalCurrency(fractDigits: 0)
}
}
let value = 34.234
func test<T: Numeric>(value: T) {
let toLocalCurrency = value.toLocalCurrency()
let result = toLocalCurrency != nil ? "\(toLocalCurrency!)" : "nil"
print(" type: \(type(of: value)), toLocalCurrency: \(result)")
}
func test<T: NSNumber>(value: T) {
let toLocalCurrency = value.toLocalCurrency()
let result = toLocalCurrency != nil ? "\(toLocalCurrency!)" : "nil"
print(" type: \(type(of: value)), toLocalCurrency: \(result)")
}
test(value: Int8(value))
test(value: Int16(value))
test(value: Int32(value))
test(value: Int(value))
test(value: Float(value))
test(value: Int16(value))
test(value: Int32(value))
test(value: Int8(value))
test(value: Double(value))
test(value: CGFloat(value))
test(value: NSNumber(value: value))