Alex
Alex

Reputation: 1625

NSString decimalValue method

I ran into some old code in a project and I do not understand why it does not crash.

Data is being ingested from an HTTP request to an API and certain values are returned as strings, but treated as NSNumbers. For example, in the code below, value is an NSString.

[NSDecimalNumber decimalNumberWithDecimal:[(NSNumber *)value decimalValue]]

However, it is incorrectly cast to an NSNumber and the decimalValue method of NSNumber is called. There is no decimalValue method for NSString, so I don't understand why the line above does not cause a crash. When I inspect value with [value isKindOfClass:[NSString class]] and [value isKindOfClass:[NSNumber class]] I get the expected results.

Is there a behavior of the runtime I do not understand? Does a cast cause the methods of a different class to be used?

edit I'm updating the title of this question to more accurately reflect the issue. The answer was that NSString has a private decimalValue method that was causing the confusion.

Upvotes: 1

Views: 127

Answers (1)

Richard J. Ross III
Richard J. Ross III

Reputation: 55593

The real answer? Voodoo. Not really, but sort of.

Lots of classes in cocoa have private methods behind the scenes. Usually, these methods go mostly unnoticed, and even more rarely used.

However, if you grab their implementation using class_getMethodImplementation and use dladdr to print the location of the symbol as such:

IMP theImp = class_getMethodImplementation([NSString class], @selector(decimalValue));
Dl_info info;
dladdr(theImp, &info);

puts(info.dli_sname);

You should see something like -[NSString(NSDecimalExtension) decimalValue].

My best guess is that this method is used for KVO & friends when marshaling values to/from decimal values, or it's used with NSNumberFormatter.

Upvotes: 1

Related Questions