Making NSDecimalNumber Codable

2020-08-23 02:07发布

问题:

Is it possible to extend NSDecimalNumber to conform Encodable & Decodable protocols?

回答1:

It is not possible to extend NSDecimalNumber to conform to Encodable & Decodable protocols. Jordan Rose explains it in the following swift evolution email thread.

If you need NSDecimalValue type in your API you can build computed property around Decimal.

struct YourType: Codable {
    var decimalNumber: NSDecimalNumber {
        get { return NSDecimalNumber(decimal: decimalValue) }
        set { decimalValue = newValue.decimalValue }
    }
    private var decimalValue: Decimal
}

Btw. If you are using NSNumberFormatter for parsing, beware of a known bug that causes precision loss in some cases.

let f = NumberFormatter()
f.generatesDecimalNumbers = true
f.locale = Locale(identifier: "en_US_POSIX")
let z = f.number(from: "8.3")!
// z.decimalValue._exponent is not -1
// z.decimalValue._mantissa is not (83, 0, 0, 0, 0, 0, 0, 0)

Parse strings this way instead:

NSDecimalNumber(string: "8.3", locale: Locale(identifier: "en_US_POSIX"))


回答2:

In swift you should use Decimal type. This type confirms to protocols Encodable & Decodable from the box.

If you have NSDecimalNumber type in your code it's easy to cast it to Decimal

let objcDecimal = NSDecimalNumber(decimal: 10)
let swiftDecimal = (objcDecimal as Decimal)


标签: swift swift4