Swift 3 十进制、NSDecimal 和 NSDecimalNumber
Posted
技术标签:
【中文标题】Swift 3 十进制、NSDecimal 和 NSDecimalNumber【英文标题】:Swift 3 Decimal, NSDecimal and NSDecimalNumber 【发布时间】:2016-12-14 17:36:59 【问题描述】:我正在尝试将 NumberFormatter
与 Swift 3 Decimal
一起使用,但我对 Decimal
的实际实现方式感到困惑。我遇到的问题是Decimal
是一个结构,所以每次我想使用格式化程序时,我都必须将它桥接到NSDecimalNumber
,我想避免这种情况。
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let decimal = Decimal(integerLiteral: 3)
let string = formatter.string(from: decimal as NSDecimalNumber)
实现我自己的采用Decimal
的扩展是理想的解决方法吗?
extension NumberFormatter
open func string(from number: Decimal) -> String?
return string(from: number as NSDecimalNumber)
更一般地说,每次我需要传入一个对象类型时,我是否需要桥接Decimal
或编写更多扩展?
编辑
我想我更普遍地想知道 Swift 3 中的 NSDecimal
Decimal
和 NSDecimalNumber
。我完全不清楚这里发生了什么。对于 Swift 3,我应该用 Decimal
替换 NSDecimalNumber
吗?文档写道:
Foundation 框架的 Swift 覆盖提供了 Decimal 结构,它连接到 NSDecimalNumber 类。 Decimal 值类型提供与 NSDecimalNumber 引用类型相同的功能,并且两者可以在与 Objective-C API 交互的 Swift 代码中互换使用。这种行为类似于 Swift 如何将标准字符串、数字和集合类型桥接到它们相应的 Foundation 类。
起初我以为Decimal
是新的NSDecimalNumber
,就像Error
是新的NSError
- 但现在我不太确定了。这还说“十进制值类型提供与 NSDecimalNumber 引用类型相同的功能”——这真的是真的吗?我似乎无法获得很多相同的功能(当然,如果不先桥接它,这就是他们的意思吗?)。我在这里和那里找到了一些帖子和一些信息,但没有什么令人信服的。有没有人有任何知识或见解?
我的应用专门使用 NSDecimalNumber
进行货币和格式设置,因此舍入和格式设置是一个高优先级。
【问题讨论】:
据我所见,NumberFormatter(style: .decimal)
不会编译,而且NumberFormatter()
不会创建一个可选项。 – 这是你的真实代码,还是我忽略了什么?
extension NumberFormatter convenience init(style: NumberFormatter.Style) self.init() self.numberStyle = style func string(from decimal: Decimal) -> String? return string(from: decimal as NSNumber)
是的,这是我的真实代码,它编译得很好。我在 Xcode 8.1 上,这在 8.2 中是否发生了变化?
在 Xcode 8.1 中无法为我编译,因为没有这样的初始化程序。
对不起,我们有一个简单的 NSNumberFormatter 扩展,代码已经更新
【参考方案1】:
我在 swift-users 板上提出了我的问题并得到了很好的答案,请在此处查看:https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161219/004220.html
响应的文本版本:
Swift 3 引入了 Decimal 类,起初我认为它应该在 Swift 中“替换” NSDecimalNumber,例如 Error 是新的 NSError 等。但是,经过进一步调查,我不清楚这实际上是这样的。看起来 Swift 3 的 Decimal 更像是一个 NSDecimal,但有一些桥接,因此它可以在需要时使用 NSDecimalNumber 的方法。我想知道的是,我应该用十进制替换我的应用程序中的 NSDecimalNumber 吗? Decimal 是 Swift 中 NSDecimalNumber 的继承者吗?
Decimal
实际上是一个结构体,而不是一个类,实际上它只是 Objective-C 中NSDecimal
结构体的 Swift 名称。在 Swift 中,NSDecimalAdd
之类的函数作为Decimal
上的运算符公开,用于满足SignedNumber
等各种数字协议的要求。
最终结果是Decimal
很像Int
或Double
——它是一种可以方便地用于进行各种数学运算的值类型。那么NSDecimalNumber
就等价于NSNumber
。
由于我的应用程序正在进行大量格式化,因此需要在 Decimal 和 NSDecimalNumber 之间进行大量转换,或者添加要使用的扩展名,所以我认为如果没有很多扩展名,这将是不自然/方便的。 Swift 是否计划改进 Decimal 使其更适用于 NumberFormatter 或其他面向对象的数字 API?希望我已经提供了足够的信息来回答我的问题。
使用NSDecimalNumber
的Objective-C API 应该桥接到Decimal
,就像NSString
桥接到String
一样。但是,这种桥接可能不适用于类别方法;你可以通过在Decimal
上编写一个扩展来将它们暴露给 Swift,它将self
转换为NSDecimalNumber
,然后调用你的 Objective-C 方法。
同样,您应该能够通过将Decimal
与NumberFormatter
一起使用,通过转换为NSDecimalNumber
,就像您将Int
或Double
转换为NSNumber
以将它们与NumberFormatter
一起使用。
【讨论】:
使用它比Double
类型有什么优势?
@brahimm 你永远不应该使用 Double/Float 来表示货币。你可以在这里阅读一个很好的解释:***.com/questions/3730019/…
@Caio 我也有同样的担忧,但我现在也担心 Swift 的 Decimal
没有解决这个问题:/以上是关于Swift 3 十进制、NSDecimal 和 NSDecimalNumber的主要内容,如果未能解决你的问题,请参考以下文章
如何声明 NSDecimal 以及如何使用 NSDecimalAdd
NSDecimal、NSDecimalNumber、CFNumber 之间的正确选择是啥?
从 `NSDecimal` 或 `NSDecimalNumber` 转换为 C# 的 `decimal` 类型