Spaniard89
Spaniard89

Reputation: 2419

'NSInvalidArgumentException' while running an application using NSURL and NSJSON

I have designed an app, which would have a button and three labels.

When the button is pressed, an URL is called. The JSON representation of the URL is as follow:

[
  {
    "_id": "50c87e8a1898044ea1458e4c",
    "value": "10",
    "time": "12:10",
    "date": "12.12.12"
  },
  {
    "_id": "50c87f311898044ea1458e4d",
    "value": "12",
    "time": "13:15",
    "date": "12.12.12"
  }
]

I also have three label in my app, that would display the value, time and date.

The code for my app is as follow:

-(IBAction)getrequest:(id)sender
{
    NSURL *url =[NSURL URLWithString:@"http://localhost:3000/lights"];
    NSData* data = [NSData dataWithContentsOfURL:url];
    //fetch the data to the JSON Foundation opject.
    [self performSelectorOnMainThread:@selector(fetchedData:)
                           withObject:data waitUntilDone:YES];
}

- (void)fetchedData:(NSData *)responseData {
    NSError *e = nil;
    NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
    NSLog(@"%@", json);
        [self processData:json];
}

-(void)processData:(NSDictionary *) JSONObject{
    NSString        *value = [JSONObject valueForKey:@"value"];
    NSString        *date    = [JSONObject valueForKey:@"date"];
     NSString        *time    = [JSONObject valueForKey:@"time"];


    NSLog(@"value: %@", value);
    NSLog(@"date: %@", date);
    NSLog(@"time: %@", time);

    _value.text = value;
    _date.text = date;
    _time.text = time;

}

The code compiles and builds without any error, but when I press the button in my simulator I get an exception as follow:

2012-12-12 14:16:21.115 Sensor_visulization[7956:11303] value: (
    10,
    12
)
2012-12-12 14:16:21.116 Sensor_visulization[7956:11303] date: (
    "12.12.12",
    "12.12.12"
)
2012-12-12 14:16:21.116 Sensor_visulization[7956:11303] time: (
    "12:10",
    "13:15"
)
2012-12-12 14:16:21.116 Sensor_visulization[7956:11303] -[__NSArrayI isEqualToString:]: unrecognized selector sent to instance 0x7191a30
2012-12-12 14:16:21.117 Sensor_visulization[7956:11303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI isEqualToString:]: unrecognized selector sent to instance 0x7191a30'

Is there any problem with my json parser?

Can I store all the values, time, date in an array?

and display the last item in the array on the label?

Any help would be really appreciated.

Upvotes: 1

Views: 251

Answers (2)

Rob
Rob

Reputation: 438407

There seems to be a general confusion about what valueForKey does when your json object is an array of dictionary entries. Midhun's answer, solves it one way, by passing only one dictionary entry to processData (which was a logical solution because your original code's declaration of NSString *value clearly implied that you were expecting only one dictionary entry to be passed to it).

But, if you want to get arrays for all three dictionary keys for your array of dictionaries, you'd use your original fetchedData, and use valueForKey against the original json object to return NSArray objects. To do that, I'd suggest, a couple of slight modifications of your original code:

- (void)fetchedData:(NSData *)responseData {
    NSError *e = nil;
    NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
    NSLog(@"%@", json);
    [self processData:json];
}

-(void)processData:(NSDictionary *) JSONObject{

    // get the three array structures

    NSArray *value = [JSONObject valueForKey:@"value"];
    NSArray *date  = [JSONObject valueForKey:@"date"];
    NSArray *time  = [JSONObject valueForKey:@"time"];

    // these log statements demonstrate that value, date, and time are arrays

    NSLog(@"value: %@", value);
    NSLog(@"date:  %@", date);
    NSLog(@"time:  %@", time);

    // now, let's grab the last object from each to populate our controls

    _value.text = [value lastObject];
    _date.text = [date lastObject];
    _time.text = [time lastObject];
}

By the way, in one of your comments, you made a parenthetical reference to wanting to chart these results. If that's the case, I might imagine that you need the dates and times combined, into NSDate objects. If you want them as NSDate objects, you could:

-(void)processData:(NSDictionary *) JSONObject{

    // get the values

    NSArray *value = [JSONObject valueForKey:@"value"];

    // get the datetimes

    NSMutableArray *datetimes = [NSMutableArray array];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"dd.MM.yy HH:mm";
    formatter.locale = [NSLocale currentLocale];

    for (NSDictionary *dictionary in JSONObject)
    {
        NSString *datetimeString = [NSString stringWithFormat:@"%@ %@", [dictionary objectForKey:@"date"], [dictionary objectForKey:@"time"]];
        NSDate *datetime = [formatter dateFromString:datetimeString];
        [datetimes addObject:datetime];
    }

    NSLog(@"values=%@", values);
    NSLog(@"datetimes=%@", datetimes);

Because your sample data features today's unique date, 12/12/12, I wasn't able to determine your date format, so I guessed you're using dd.MM.yy, but obviously use whatever date format string makes sense for your JSON data.

Upvotes: 2

Midhun MP
Midhun MP

Reputation: 107231

json is a NSMutableArray you are passing it to processData method as NSDictionary parameter.

 NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];

Change the method call like:

[self processData:[json objectAtIndex:0]];

The above will display first element. If you need to display the last element use:

[self processData:[json objectAtIndex:[json count]-1]];

Upvotes: 1

Related Questions