1

Receiving the following error. I believe it has to do with the NSDictionary in the results of JSON array. I.e. NSDictionary within an NSDictionary maybe?

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

This is the JSON service when called. This is printed directly out of XCode but it looks clean to me.

    Printing description of self->metArray:
{
    weatherObservation =     {
        ICAO = YBBN;
        clouds = "few clouds";
        cloudsCode = FEW;
        countryCode = AU;
        datetime = "2014-11-24 03:00:00";
        dewPoint = 20;
        elevation = 5;
        hectoPascAltimeter = 1014;
        humidity = 61;
        lat = "-27.38333333333333";
        lng = "153.1333333333333";
        observation = "YBBN 240300Z 02019KT 9999 FEW029 SCT250 28/20 Q1014";
        stationName = "Brisbane Airport M. O";
        temperature = 28;
        weatherCondition = "n/a";
        windDirection = 20;
        windSpeed = 19;
    };
}

This is the code that invokes the JSON service.

 -(void)getMetar{

   // NSString *location = @"YBBN";
    NSString * const metarUrl =@"http://api.geonames.org/weatherIcaoJSON?ICAO=YBBN&username=demo";

    NSURL *url2 = [NSURL URLWithString:metarUrl];
    NSData *data2 = [NSData dataWithContentsOfURL:url2];

    metArray = [NSJSONSerialization JSONObjectWithData:data2 options:kNilOptions error:nil];

    //Create an NSDictionary for the weather data to be stored.
    NSDictionary *metarJson = [NSJSONSerialization JSONObjectWithData:data2 options:kNilOptions error:nil];

    //Loop through the JSON array
    NSArray *currentMetarArray = metarJson[@"weatherObservation"];

    //set up array and json call
    metarArray = [[NSMutableArray alloc]init];
   for (NSDictionary *metaritem in currentMetarArray)
    {
        //create our object
        NSString *nClouds = [metaritem objectForKey:@"clouds"];
        NSString *nObservation = [metaritem objectForKey:@"observation"];

        //Add the object to our animal array
        [metarArray addObject:[[metar alloc]initWithclouds:(nClouds) andobservation:nObservation]];

    }
}

It looks okay to me but maybe that is because I have been looking at it for hours.

Any ideas?

4
  • Google "unrecognized selector" and see what it means. Then learn how to get a proper exception stack trace so you can identify the failing line. Commented Nov 24, 2014 at 3:57
  • But one point is that there's no array in your JSON. Go to json.org and learn the JSON syntax. Commented Nov 24, 2014 at 3:58
  • Hi Hot Licks, Good point I hadn't thought of doing a search on how to get the "unrecognized selector". Still new at iOS but each day seems to be getting better thanks! Commented Nov 24, 2014 at 4:36
  • Always Google first. You learn a lot more that way than you do by coming here and asking someone to find your problem. Commented Nov 24, 2014 at 12:56

3 Answers 3

2
 NSArray *currentMetarArray = metarJson[@"weatherObservation"];
 for (NSDictionary *metaritem in currentMetarArray)

These lines are wrong. currentMetarArray is a dictionary, not array, it contains string key & value, so you should access it like in following way-

NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; NSDictionary *weatherObservation = [jsonDictionary objectForKey:@"weatherObservation"];

then to get nCloud, use like NSString *nClouds = [weatherObservation objectForKey:@"clouds"];

Sign up to request clarification or add additional context in comments.

2 Comments

Hi Russel, nailed it! Man both you and minh helped If I could give credits I would! I thought that having two dictionary's was the key just didn't know syntax how to do it (still newbie status). awesome sauce man.
totally helped. Both you and Minh. Thanks again guys!
1

I go to your URL and get this message {"status":{"message":"the daily limit of 30000 credits for demo has been exceeded. Please use an application specific account. Do not use the demo account for your application.","value":18}}

But you can try my code, it worked for me

NSString *strUrl = @"http://api.geonames.org/weatherIcaoJSON?ICAO=YBBN&username=demo";
NSURL *url = [NSURL URLWithString:strUrl];
NSData *data = [NSData dataWithContentsOfURL:url];

NSError *error;

NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];

NSDictionary *weatherObservation = [json objectForKey:@"status"];

for (id key in weatherObservation) {
    id value = [weatherObservation objectForKey:key];

    NSLog(@"key = %@, value = %@", key, value);
}

2 Comments

Hi Minh, sorry forgot to mention that I took out my users credentials in order for security. I do get back information. I'll review your suggestions now. thanks!
Okay I see what you have done. What you have done is correct. I just to work out each element within the returned value. i.e. temperature, wind speed etc. within the for loop.
0

The error thrown is the best clue for how you can fix this.

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

What this means is that you're thinking an object is a dictionary when in reality it isn't.

You can combat this using NSObject methods such as:

[myObject respondsToSelector:(@selector(objectForKey:))]; // will return a boolean value.

to see if the object will respond to the method you hope to send it

or

[myObject isKindOfClass:[NSDictionary class]]; // will return a boolean value.

to determine if the object is a NSDictionary.

What's likely happening, though, is that you have an error in expectation with the Deserialized JSON Data.

Happy bug hunting!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.