objective-cios8nsdecimalnumber

{NSDecimalNumber integerValue} behaving strangely in iOS8


OK team, this is weird. [NSDecimalNumber integerValue] is behaving strangely.

I'm sat at a breakpoint, trying to figure out why some parts of my app are broken in iOS8, and I'm looking at a variable called "timeSeconds". It appears like this in the Xcode Variables View:

_timeSeconds    (NSDecimalNumber *) 344.514533996581994496

But when I query it in the debugger, I see this:

(lldb) p [self.timeSeconds doubleValue]
(double) $14 = 344.51453399658192
(lldb) p [self.timeSeconds intValue]
(int) $15 = 344
(lldb) p [self.timeSeconds integerValue]
(NSInteger) $16 = -5
(lldb) p (NSInteger)[self.timeSeconds intValue]
(NSInteger) $17 = 344

See that "-5"? Can any of you beautiful people reproduce or explain that, before I file a radar?

Here's the SSCCE:

NSDecimalNumber *n = [NSDecimalNumber decimalNumberWithString:@"344.514533996581994496"];
NSLog(@"%@", n); // 344.514533996581994496
NSLog(@"%ld", (long)[n intValue]); // 344
NSLog(@"%ld", (long)[n integerValue]); // -5
NSLog(@"%ld", (long)[n unsignedIntegerValue]); // 12

Thanks in advance!

Matthew


Solution

  • The result for integerValue is surprising, but from what I understand as documented:

    NSDecimalNumber inherits from NSNumber. In the subclassing notes from NSNumber it is stated that "... subclass must override the accessor method that corresponds to the declared type—for example, if your implementation of objCType returns “i”, you must override intValue ..."

    objCType is set to the inner pointer, so it should be the same as for NSNumber.

    NSDecimal does not override intergerValue. It does override doubleValue, so that should work fine.

    The only thing that makes me wonder: it seems it does not override intValue either ...