Matt Mc
Matt Mc

Reputation: 9297

NSNumber to NSString conversion with stringValue fails

Okay, so there's another similar question that I found to this on SO but the guy was sending a stringValue message to an array, and I have a different situation.

This is the line of code that is dying:

AppModel.instance.loginDataObject.uid.stringValue

Just for debug purposes, I put it into an NSLog, like so:

NSLog(@"uid stringValue: %@", AppModel.instance.loginDataObject.uid.stringValue);

The exception that is being thrown is:

-[__NSCFString stringValue]: unrecognized selector sent to instance 0xa8525d0

Now, "uid" is an NSNumber, as declared in loginDataObject's header file:

#import "Jastor.h"

@interface LDLoginData : Jastor
@property (nonatomic, strong)   NSString    *api_login_key;
@property (nonatomic, strong)   NSString    *clazz_reg_code;
@property (nonatomic, strong)   NSNumber    *current_clazz;
@property (nonatomic, strong)   NSString    *mail;
@property (nonatomic, strong)   NSString    *name;
@property (nonatomic, strong)   NSString    *profile_first_name;
@property (nonatomic, strong)   NSString    *profile_last_name;
@property (nonatomic, strong)   NSNumber    *teacher_id;
@property (nonatomic, strong)   NSNumber    *uid;
@property (nonatomic, strong)   NSString    *user_type;
@property (nonatomic, strong)   NSNumber    *va_user_clazz_id;
@end

Note that I am using the Jastor class to populate the loginDataObject.

Further, debugger commands show it's an NSNumber:

po AppModel.instance.loginDataObject.uid
(NSNumber *) $1 = 0x0a8525d0 7593

But somehow it doesn't respond to the stringValue selector:

po AppModel.instance.loginDataObject.uid.stringValue
error: property 'stringValue' not found on object of type 'NSNumber *'
error: 1 errors parsing expression

Even though this method is clearly documented.

Now, if I call the description method on the uid object:

po AppModel.instance.loginDataObject.uid.description
error: property 'description' not found on object of type 'NSNumber *'
error: 1 errors parsing expression

It doesn't like it in the console, but if I change my code to this:

NSLog(@"uid stringValue: %@", AppModel.instance.loginDataObject.uid.description);

The code executes and I get this in the console:

2012-09-29 15:02:11.829 MyApp[28661:c07] uid stringValue: 7593

So, what's happening?

Upvotes: 0

Views: 1646

Answers (1)

Matt Mc
Matt Mc

Reputation: 9297

I answered my own question while I was writing it, so I figured I may as well go ahead and post it, and post the answer.

The key point that I overlooked was the exception itself:

-[__NSCFString stringValue]: unrecognized selector sent to instance 0xa8525d0

So, the "uid" object that I was sending -stringValue to was actually an NSString object at heart, even though it had been cast as an NSNumber.

The reason why this had happened is because of the data source. My App downloads a JSON blob, deserializes it into NSDictionary, NSArray, NSString and NSNumber objects, and then passes it to Jastor which pumps it into a structure of "frame" classes that I set up (consisting purely of properties, one example is above in my question).

So the sequence was:

JSON -> NSDictionary -> loginDataObject

The problem arose when I was writing loginDataObject's class, and I made uid an NSNumber (it is numeric all of the time).

However, for some reason the JSON serializer on the website that I'm downloading the blob from puts quotes around this uid value, making it a string. Then, when I deserialize the JSON, it becomes an NSString instead of an NSNumber. Jastor, not knowing any better, sticks a pointer to the string into my NSNumber *uid property, and the rest is history.

Really, the lesson would be to pay a bit more attention to the exact exception thrown, and to more closely scrutinize JSON that one is deserializing.

Upvotes: 2

Related Questions