Search code examples
objective-cnsdictionarysbjson

NSDictionary objectForKey throws Exception NSCFString


This is my code:

    NSError *error = nil;
    SBJsonParser *parserJson = [[SBJsonParser alloc] init];
    NSDictionary *jsonObject = [parserJson objectWithString:webServiceResponse error:&error]; 
    [parserJson release], parserJson = nil;

    //Test to see if response is different from nil, if is so the parsing is ok
    if(jsonObject != nil){
        //Get user object
        NSDictionary *userJson = [jsonObject objectForKey:@"LoginPOST2Result"];
        if(userJson != nil){
            self.utente = [[User alloc] init];
            self.utente.userId = [userJson objectForKey:@"ID"];
        }

While Json string webServiceResponse is:

{"LoginPOST2Result":
    "{\"ID\":1,
    \"Username\":\"Pippo\",
    \"Password\":\"Pippo\",
    \"Cognome\":\"Cognome1\",
    \"Nome\":\"Nome1\",
    \"Telefono\":\"012345678\",
    \"Email\":null,
    \"BackOffice\":true,
    \"BordoMacchina\":false,
    \"Annullato\":false,
    \"Badge\":1234}"
}

The problem arise when is execute this line:

self.utente.userId = (NSInteger *) [userJson objectForKey:@"ID"];

and the error is:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectForKey:]: unrecognized selector sent to instance 0x6861520'

The error seems to be due to the fact that the object userJson is not an NSDictionary but rather NSCFString type and therefore does not respond to the message objectForKey:.
Where am I doing wrong?


Solution

  • You need to better understand what is a pointer and what no in the Cocoa Framework.

    Infact you are defining userJson to NSDictionary and not NSDictionary *. Consider that all objects in Cocoa are pointers. Infact check that [NSDictionary objectForKey:] returns an "id" and then you must use NSDictionary *. Using simply NSDictionary you will refer to the class.

    Similar mistake is done later in the cast to (NSInteger *) but NSInteger (NSInteger is not an object, it's a basic type hesitated from long or int (depends on the platform architecture) as you can see from its definition:

    
    #if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
    typedef long NSInteger;
    #else
    typedef int NSInteger;
    #endif
    

    And also it seems from the object definition above that the key you are trying to get is dumped as a string and you are trying to fetch a dictionary. Please check the original json which probably is not in the format you expect.

    So at the end you have at least 3 errors that will make your app crash.