0

Part of my app gets JSON data and uses it to display updates. There's two parts to the initial JSON response: an error and an update section.

The following is the array you get when doing [JSONData objectForKey:@"updates"]; to isolate the update section

{
2 =     {
    message = "Best restaurant ever!";
    name = " ";
    profilePictureURL = "<null>";
    restPictureURL = "http://i.imgur.com/QpyMRwY.jpg";
    restaurant = "someplace";
    timestamp = 1390194000;
};
3 =     {
    message = "Ehh.";
    name = " ";
    profilePictureURL = "<null>";
    restPictureURL = "http://i.imgur.com/QpyMRwY.jpg";
    restaurant = "someplace";
    timestamp = 1389848400;
};
4 =     {
    message = "";
    name = " ";
    profilePictureURL = "<null>";
    restPictureURL = "http://i.imgur.com/QpyMRwY.jpg";
    restaurant = "McDonald's";
    timestamp = 1390346335;
};
5 =     {
    message = "Service was slow.";
    name = " ";
    profilePictureURL = "<null>";
    restPictureURL = "http://i.imgur.com/QpyMRwY.jpg";
    restaurant = "Bad pizzaplace";
    timestamp = 1389330000;
};
}

Then I pass this NSArray to a function which formats it to a class I designed for updates and then appends that update to a NSMutableArray stored in AppDelegate.

@implementation Update
+(void) appendUpdates:(NSArray*)data
{


    AppDelegate* appDelegate=  [[UIApplication sharedApplication]delegate];
    for (NSDictionary* currentUpdate in data)
    {
        Update* formattedUpdate = [[Update alloc]initWithDict:currentUpdate];
        [appDelegate.updateList addObject:formattedUpdate];
    }

}
-(id) initWithDict:(NSDictionary*)update
{
    self = [super init];
    self.name = [update objectForKey:@"name"];
    self.restaurant = [update objectForKey:@"restaurant"];
    self.message = [update objectForKey:@"message"];
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:(int)[update objectForKey:@"timestamp"]];
    self.timestamp = date;
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:date];
    self.dateComponents = components;
    self.profilePictureURL = [update objectForKey:@"profilePictureURL"];
    self.restaurantPictureURL = [update objectForKey:@"restPictureURL"];
    return self;
}

@end

pastebin

When I run the code, I receive an error inside the initialization method when trying to use objectForKey:.

Any ideas? Thanks in advance

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
jtmarmon
  • 5,727
  • 7
  • 28
  • 45
  • 1
    What's the error says? – Kumar KL Jan 22 '14 at 04:35
  • `-[__NSCFString allKeys]: unrecognized selector sent to instance 0x9bc5380 2014-01-21 23:55:25.938 MyApp[49350:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString allKeys]: unrecognized selector sent to instance 0x9bc5380'` – jtmarmon Jan 22 '14 at 04:57
  • @JasonMarmon : Have a look at the JSON format. In My answer. – Balram Tiwari Jan 22 '14 at 05:25
  • What trouble did you have when formatting the code? it is easy: paste it in, select the code, hit the source code button. – vikingosegundo Jan 22 '14 at 05:52

3 Answers3

0

Try this, Change your appendUpdates: method to

+(void) appendUpdates:(NSArray*)data
{
    AppDelegate* appDelegate=  [[UIApplication sharedApplication]delegate];
    for (NSDictionary* currentUpdate in data)
    {
        NSString *key = [[currentUpdate allKeys] objectAtIndex:0];
        currentUpdate = [currentUpdate objectForKey:key];
        Update* formattedUpdate = [[Update alloc]initWithDict:currentUpdate];
        [appDelegate.updateList addObject:formattedUpdate];
    }

}
Akhilrajtr
  • 5,170
  • 3
  • 19
  • 30
  • Didn't work =/ I think it has to do with the beginning and trailing brackets on the JSON data, but I'm not sure how to remove them – jtmarmon Jan 22 '14 at 04:57
0

A clean solution is to just create a dictionary object inside your Update class & then add your keyValues & return that dictionary. Also keep in mind what you want to use to access values from dictionary valueForKey or objectForKey. They both have difference. Read here in short.

May be you can format your JSON file

{
"updates":
 [
   {
     "ID":1,
     "SystemCovered":"Dept/State Outage Reporting",
     "InchargeFirstName":"Davids",
   },
    {
      "ID":2,
      "SystemCovered":"State Outage Reporting",
      "InchargeFirstName":"Davids-123",
   },
    {
      "ID":2,
      "SystemCovered":"Reporting",
      "InchargeFirstName":"Davids-234",
    }
 ]
}

A THUMB RULE

While parsing JSON, Whenever you encounter [ ], treat it as an Array & whenever you see '{ }', treat is at dictionary.

I hope that helps.

Community
  • 1
  • 1
Balram Tiwari
  • 5,657
  • 2
  • 23
  • 41
  • I can't imagine why I would need to subclass from NSDictionary. Returning an instance of `self` when the method is inside of class `Update` should return an Update object, which is what an init method should do. I think the error is incorrectly formatted JSON, so I'll talk to my backend person tomorrow to get it fixed – jtmarmon Jan 22 '14 at 05:17
  • You may be correct, I am not denying as I was not knowing what error you got. Now I can see, you have posted the exception. – Balram Tiwari Jan 22 '14 at 05:20
  • Yep. I figured out the JSON problem right when you did. Because I can't change what happens on the server side, I got the array members using "objectForKey:@"1...2...3..."" But this is definitely the best answer for anyone else that stumbles upon this. – jtmarmon Jan 22 '14 at 05:28
  • Ok, Adding one thumb Rule also: Whenever you encounter `[ ]`, treat it as an `Array` & when you see `{ }`, treat is at `dictionary`. – Balram Tiwari Jan 22 '14 at 05:57
0

Change your method as +(void) appendUpdates:(NSDictionary*)data instead +(void) appendUpdates:(NSArray*)data. Because you have Dictionary(not an array) which contains dictionary of object.

And your method definition should be..

+(void) appendUpdates:(NSDictionary*)data
{
    AppDelegate* appDelegate=  [[UIApplication sharedApplication]delegate];
    for (NSString* key in [data allKeys])
    {
        NSDictionary *currentUpdate = [data objectForKey:key];
        Update* formattedUpdate = [[Update alloc]initWithDict:currentUpdate];
        [appDelegate.updateList addObject:formattedUpdate];
    }

}
Mani
  • 17,549
  • 13
  • 79
  • 100