Why NSDecimalNumber(string:"2175613.285964774433431797660").intValue = 0
NSDecimalNumber(string:"2175613.285964774433431797660").int32Value = 2175613
NSDecimalNumber(string:"2175613.285964774433431797660").int64Value = 0
Who can help me?
You can avoid confusion about the decimal separator by calling init(string:locale:)
, passing in a fixed locale. For example:
let enGB = Locale(identifier: "en_GB")
let d = NSDecimalNumber(string: "2175613.28", locale: enGB)
Having said that, there’s definitely something weird going on here. First, let’s deal with the Swift side of this. The Swift intValue
property returns a Swift Integer
, which is the size of a pointer. This means that it doesn’t call the -[NSNumber intValue]
method, because that always returns a CInt
, aka an Int32
. Rather, it calls the -integerValue
method.
Some poking around in the debugger reveals that -integerValue
is implemented in the superclass, NSNumber
, and it just calls -longValue
and returns that. -longValue
is implemented in NSDecimalNumber
.
So, to investigate further I switched to Objective-C:
@import Foundation;
int main(int argc, char **argv) {
NSLocale * enGB = [NSLocale localeWithLocaleIdentifier:@"en_GB"];
NSDecimalNumber * d = [[NSDecimalNumber alloc] initWithString:@"2175613.285964774433431797660" locale:enGB];
NSLog(@"%@", d); // 2175613.285964774
NSLog(@"%f", d.doubleValue); // 2175613.285965
NSLog(@"%d", d.intValue); // 2175613
NSLog(@"%zd", d.integerValue); // 0
NSLog(@"%ld", d.longValue); // 0
return EXIT_SUCCESS;
}
This makes it clear that the Swift intValue
is failing because -[NSDecimalNumber longValue]
is failing. And I’ve no idea why that is. I stepped through the assembly in the debugger and it’s doing a bunch of stuff that looks kinda like the stuff you’d expect it to do, but I don’t know enough about how this type works to offer an informed opinion as to why it’s failing.
Regardless, I think it’s bugworthy. The fact that -intValue
works but -longValue
fails can’t be anything other than a bug, and I encourage you to file it as such. Please post your bug number, just for the record.
The workaround seems pretty straightforward: Use the int32Value
property. Or use doubleValue
property and truncate the fractional part.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"