iOS NSDictionary error - iphone

I'm parsing a JSON here and am getting the data correctly. However, when I try to put the info in an NSDictionary and the read it, I get this error
'NSInvalidArgumentException', reason: '-[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0x1cda3d50'
heres the code
if (data != nil) {
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
NSDictionary *dic = [[res objectForKey:#"data"] objectForKey:#"current_condition"];
self.location = [[dic objectForKey:#"request"]objectForKey:#"query"];
}
Any idea on whats going wrong here? Thanks.
EDIT
this is what i get when i log NSDictionary *res
data = {
"current_condition" = (
{
cloudcover = 100;
humidity = 86;
"observation_time" = "11:11 PM";
precipMM = "2.2";
pressure = 1019;
"temp_C" = 1;
"temp_F" = 34;
visibility = 8;
weatherCode = 296;
weatherDesc = (
{
value = "Light rain";
}
);
weatherIconUrl = (
{
value = "http://www.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0033_cloudy_with_light_rain_night.png";
}
);
winddir16Point = SSW;
winddirDegree = 210;
windspeedKmph = 15;
windspeedMiles = 9;
}
);
request = (
{
query = "North Massapequa, United States Of America";
type = City;
}
);
}

Your JSON object probably contains an array somewhere where you expected a dictionary (you sent objectForKey: to an array object).
Try dumping the JSON somewhere and make sure it's in the format you expect.
EDIT: As you can see from the dump, res[#"request"] is an array (it has ()). Thus, you are calling objectForKey:#"query" on the request array and crashing.
Try self.location = [[[res objectForKey:#"request"] objectAtIndex:0] objectForKey:#"query"]; instead.

You're misinterpreting the output of the NSDictionary log, helped by what I believe to be a long-standing bug.
The output looks like this:
data = {
"current_condition" = (
{
cloudcover = 100;
This hides the actual shape of the data. See the long break after the = on the data, current_condition, weatherDesc, etc lines? There should be a line break there, so the output looks like this:
data =
{
"current_condition" =
(
{
cloudcover = 100;
The () indicates an array. (Yes, even though [] is used elsewhere. This output is old and crusty, and I doubt Apple could fix it without breaking code even if they suddenly decided it was important.)
This shows the true shape of the data: current_condition is an array. The dictionary is the first (index 0) object in the array, not the array itself.
Across the whole data, this would look like this:
data =
{
"current_condition" =
(
{
cloudcover = 100;
humidity = 86;
"observation_time" = "11:11 PM";
precipMM = "2.2";
pressure = 1019;
"temp_C" = 1;
"temp_F" = 34;
visibility = 8;
weatherCode = 296;
weatherDesc =
(
{
value = "Light rain";
}
);
weatherIconUrl =
(
{
value = "http://www.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0033_cloudy_with_light_rain_night.png";
}
);
winddir16Point = SSW;
winddirDegree = 210;
windspeedKmph = 15;
windspeedMiles = 9;
}
);
}
Adjust your code appropriately for the extra level of indirection and you should be fine.

-[__NSCFArray objectForKey:]: unrecognized selector - you can see here that, obviously, you're trying to call objectForKey: on array.
Here:
self.location = [[dic objectForKey:#"request"]objectForKey:#"query"];
dic is an array:
data = {
"current_condition" = ( // <--- array
probably you wanted to do:
self.location = [[res objectForKey:#"request"]objectForKey:#"query"]; // res, not dic
but request is also an array and you'll still get exactly same error...

Related

How to read values from NSArray of NSDictionaries

I have an array of NSDictionary values that looks like this when NSLogged
{
HASMOD = F;
ISLOCKED = F;
ISREGD = F;
MANU = "HORNET";
ID = 706;
},
{
HASMOD = T;
ISLOCKED = F;
ISREGD = T;
MANU = "BANJI";
ID = 225;
},
//etc
I am trying to save these values to my core data object (with correct types). I have been following this tutorial and have reached the point where I am trying to insert the values into each of the objects, However I am not sure how to do this from an array of dictionaries.. as it only shows how to enter one lot of information
So I have attempted doing it myself.. but its more pseudo code than anything... this is as far I have as I done... hopefully it helps make sense of what I am trying to achieve.
// WRITE TO CORE DATA
NSManagedObjectContext *context = [self managedObjectContext];
Manuf *manuf = [NSEntityDescription insertNewObjectForEntityForName:#"Manuf" inManagedObjectContext:context];
int mycount = [parsedDataArrayOfDictionaries count];
while (mycount != 0) {
// Somehow read Dictionaries and put them into their correct value types
BOOL hasModBool;
hasModelBool =
BOOL isLockedBool;
isLockedBool =
BOOL isRegedBool;
isRegedBool =
NSString *manuString = [[NSString alloc] init];
manuString =
int manuIDInt;
manuIDInt =
// pass all the values into the manuf coredata obj
manuf.hasMod = hasModBool;
manuf.isLocked = isLockedBool;
manuf.isReged = isRegedBool;
manuf.manu = manuString;
manuf.manuID = manuIDInt;
count --; // itterate through the array
}
I am hoping someone can help me run through the array of dictionaries and insert them into the variables of my core data object..
any help would be greatly appreciated.
Just use a for-in loop to iterate through your array, and get the values with valueForKey:.
for (NSDictionary *dict in parsedDataArrayOfDictionaries) {
Manuf *manuf = [NSEntityDescription insertNewObjectForEntityForName:#"Manuf" inManagedObjectContext:context];
BOOL hasModelBool;
BOOL isLockedBool;
BOOL isRegedBool;
if([dict valueForKey:#"HASMOD"] isEqualToString:#"T"]) {
hasModelBool = TRUE;
}else{
hasModelBool = FALSE;
if([dict valueForKey:#"ISLOCKED"] isEqualToString:#"T"]) {
isLockedBool = TRUE;
}else{
isLockedBool = FALSE;
......
......
// pass all the values into the manuf coredata obj
manuf.hasMod = hasModBool;
manuf.isLocked = isLockedBool;
manuf.isReged = isRegedBool;
manuf.manu = manuString;
manuf.manuID = manuIDInt;
}
I'm assuming here that the "T" or "F" values in your dictionaries are strings that need to be converted to TRUE or FALSE.

loop through NSDictionary to create NSArray

I have the following NSDictionary data:
{
"ADDED_DATE" = "2011-02-04 00:56:44.732014";
"ADDED_LOGON" = ABCD;
"AGENT_BROKER_IND" = N;
"ALLOCATION_IND" = AUTOPROP;
"BILLPRINT_DLVY_IND" = PAPER;
"BILLPRINT_LOCATION_NAME" = "COMPANY ABC";
"BILLPRINT_LVL_CIM" = 05852015;
"BILL_DUE_DT" = "2011-02-01";
"BILL_LOGO_CD" = XXLOGO;
"BILL_PERIOD_MONTH" = 02;
"BILL_PER_BEG_DT" = "2011-02-01";
"BILL_PER_END_DT" = "2011-02-28";
"BILL_RUN_DT" = "2011-02-03";
"BILL_TOTAL_PREMIUM" = "342.84";
IDX = ".000339709222474931";
"LIST_BILL_CASE_NUM" = 0318T4;
"LIST_BILL_CIM" = 05852019;
"OWNING_CARRIER" = WX;
"PAST_DUE_DT" = "2011-03-04";
"REMIT_CYCLE" = MONTHLY;
"RUN_NUMBER" = 1;
"TOTAL_ADJUSTMENTS" = "0.00";
"TOTAL_AMOUNT_DUE" = "685.68";
"TOTAL_CURRENT_CHARGES" = "342.84";
"TOTAL_PASTDUE_AMOUNT" = "342.84";
},
{
"ADDED_DATE" = "2010-12-04 08:20:45.292516";
"AGENT_BROKER_IND" = N;
"ALLOCATION_IND" = AUTOPROP;
"BILLPRINT_DLVY_IND" = WEBPORTAL;
"BILLPRINT_LOCATION_NAME" = "ANCHOR ABC";
"BILLPRINT_LVL_CIM" = 05721991;
"BILL_DUE_DT" = "2010-12-15";
"BILL_FORM_TYPE_CD" = FE4;
"BILL_LOGO_CD" = XXLOGO;
"BILL_PERIOD_MONTH" = 01;
"BILL_PER_BEG_DT" = "2011-01-01";
"BILL_PER_END_DT" = "2011-01-31";
"BILL_RUN_DT" = "2010-12-03";
"BILL_TOTAL_PREMIUM" = "277.96";
IDX = ".000389371998789428";
"LIST_BILL_CASE_NUM" = 9858Q8;
"LIST_BILL_CIM" = 05721991;
"OWNING_CARRIER" = FE;
"PAST_DUE_DT" = "2010-12-31";
"REMIT_CYCLE" = MONTHLY;
"RUN_NUMBER" = 1;
"TOTAL_ADJUSTMENTS" = "0.00";
"TOTAL_AMOUNT_DUE" = "277.96";
"TOTAL_CURRENT_CHARGES" = "277.96";
"TOTAL_PASTDUE_AMOUNT" = "0.00";
},
And I am trying to figure out how convert this data into arrays. With this example I need to have it broken down into 2 arrays with those arrays filled with it's data (hope that made sense).
I can loop through the data like this:
NSString *key;
for (key in finalDict) {
NSLog(#"%#", key);
}
And I get each "array" of data in "key" ... but how to I break it down from there into it's own arrays? Sorry if I'm confusing. =)
Thanks for any help!
So, it looks to me like you have an NSArray of NSDictionaries, judging by your code. If you actually want to load all the data into a UITableView I would suggest that in your cellForRowAtIndexPath method, you create an NSDictionary and load it with the current indexes NSDictionary like this:
NSDictionary *currentDictionary = [self.myArrayOfDictionaries objectAtIndex:indexPath.row];
//now do some stuff with your dictionary
cell.addedDate.text = [currentDictionary objectForKey:#"ADDED_DATE"];
cell.agentBrokerInd.text = [currentDictionary objectForKey:#"AGENT_BROKER_IND"];
///etc.....
Of course, it depends on how you set up your UITableViewCell and whether or not you want to have outlets for each attribute or not.
Hope this helps.
Make key an NSArray type instead of NSString. Then you can access the array's elements, adding them to another array or whatever else you want to do. Here is the NSArray documentation.

sorting array of nested NSDictionary containing an array

Im quite new to iOS and objective.. heres my question..
if my array looks like this:
myArray = {
parentdict = {
childdict = {
aname = "Aname";
bname - "Bname";
cname = "Cname";
};
childarray = {
{
counter = "1";
close = "25236";
},
{
counter = "2";
close = "12458";
};
};
};
},
{
parentdict = {
childdict = {
aname = "Aname";
bname - "Bname";
cname = "Cname";
};
childarray = {
{
counter = "1";
close = "28556";
},
{
counter = "2";
close = "12118";
};
};
};
},
{
parentdict = {
childdict = {
aname = "Aname";
bname - "Bname";
cname = "Cname";
};
childarray = {
{
counter = "1";
close = "24356";
},
{
counter = "2";
close = "155628";
};
};
};
};
basically its an array of nested dictionary and inside one of the dictionary contains an array of dictionary (childarray) if i want to sort myArray by #"close" of array index 1, which is the one next to counter 2, exactly how should i do this?..(perhaps i should use NSSortDescriptor?)
thanks for the reply
You have presented your structure in the JSON format. I assume it is for sake of presenting it to the audience here. If you are actually starting with JSON string, you will have to convert it to nested NSArrayies and NSDictionaryies using some third-party libs or iOS 5 built-in classes..
Assuming you already have your top level NSArray* myArray, give it a try to the following code:
NSArray* myArray = // ... this is your array
NSArray* sorted_array = [myArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary* left = obj1;
NSDictionary* right = obj2;
NSDictionary* left_parent_dict = [left objectForKey: #"parentdict"];
NSDictionary* right_parent_dict = [right objectForKey: #"parentdict"];
NSArray* left_child_array = [left_parent_dict objectForKey: #"childarray"];
NSArray* right_child_array = [right_parent_dict objectForKey: #"childarray"];
NSDictionary* left_child_first = [left_child_array objectAtIndex: 1];
NSDictionary* right_child_first = [right_child_array objectAtIndex: 1];
NSString* left_close = [left_child_first objectForKey: #"close"];
NSString* right_close = [right_child_first objectForKey: #"close"];
NSNumber* left_val = [NSNumber numberWithInt: [left_close intValue]];
NSNumber* right_val = [NSNumber numberWithInt: [right_close intValue]];
return [left_val compare: right_val];
} ];
You will need, of course, to add some checks which I omitted for simplicity.
If you want to get descending order modify the last statement to:
return [right_val compare: left_val];
I would also suggest you considering SQL database for complex data structures as pointed out by Niko.
Sorting an array can be quite complex, especially when the array contains nested objects. May be you should create an SQLite database
You should use iOS 5.0's built in JSON API. [Here's a link to a great tutorial.] (http://www.raywenderlich.com/5492/working-with-json-in-ios-5). JSON is really easy to work with. And that site also has great tutorials on Core Data (iOS's SQLite API) here. There are two more parts to that tutorial as well.
Try this
[array sortUsingComparator:(NSComparator)^(id obj1, id obj2){
int firstValue = [[obj1 objectForKey:#"someKey"] intValue];
int secondValue = [[obj2 objectForKey:#"someKey"] intValue];
int valueDiff = firstValue - secondValue;
return (valueDiff == 0) ? NSOrderedSame : (valueDiff < 0) ? NSOrderedAscending : NSOrderedDescending;
}];

How do I properly populate the UITableView NSArray from a NSDictionary created using JSONKit?

Sorry for the long question but that best summarizes what I am trying to do:
My JSON Looks like:
{
4e8cf1d6c7e24c063e000000 = {
"_id" = {
"$id" = 4e8cf1d6c7e24c063e000000;
};
author = faisal;
comments = (
{
author = adias;
comment = amazing;
},
{
author = nike;
comment = "I concur";
}
);
created = {
sec = 1317772800;
usec = 0;
};
text = "This is a random post";
title = "post # 1";
type = (
punjabi
);
};
4e91fd49c7e24cda74000000 = {
"_id" = {
"$id" = 4e91fd49c7e24cda74000000;
};
author = draper;
comments = (
{
author = adias;
comment = "amazing again";
}
);
created = {
sec = 1318118400;
usec = 0;
};
text = "This is a random post again";
title = "post # 2";
type = (
punjabi
);
};
}
What I would like to do is to ultimately have a UTTableview with each row having a title (text from above JSON):
This is the code I have so far:
NSString *responseString = [request responseString];
NSDictionary *resultsDictionary = [responseString objectFromJSONString];
How do I put everything in an array for the UITableView? Again I am just a little rusty as I can swear I have done that before.
If you don't need the keys then you can convert it to an array by using allValues, e.g.:
NSArray *values = [resultsDictionary allValues];
Does your JSON really parse to an NSDictionary, or is this an NSArray containing NSDictionary instances? If the latter, then isn't it just something like:
NSString *textForCell = [[resultsArray objectAtIndex:row] valueForKey:#"title"];

Trouble reading JSON object using Obj-C

I am trying to read the following json object using the json-framework and obj-C
{
Sections = {
Now = "Wednesday 9 February 2011 02:40";
Section = (
{
Article = (
{
Exceprt = "text here";
ID = 49011;
Title = "text here";
Type = Politics;
audioCounter = 0;
commentsCounter = 0;
hasMore = false;
important = False;
likesCounter = 0;
photoCounter = 0;
time = "21:12";
timeStamp = "2/8/2011 9:14:16 PM";
timeStatus = True;
videoCounter = 0;
viewsCounter = 0;
},
{
Exceprt = "text here";
ID = 49010;
Title = "text here";
Type = Politics;
audioCounter = 0;
commentsCounter = 0;
hasMore = false;
important = True;
likesCounter = 0;
photoCounter = 0;
time = "20:45";
timeStamp = "2/8/2011 9:10:59 PM";
timeStatus = True;
videoCounter = 0;
viewsCounter = 0;
},
{
Exceprt = "text here";
ID = 49008;
Title = "text here";
Type = Politics;
audioCounter = 0;
commentsCounter = 0;
hasMore = false;
important = False;
likesCounter = 0;
photoCounter = 0;
time = "20:28";
timeStamp = "2/8/2011 9:09:44 PM";
timeStatus = True;
videoCounter = 0;
viewsCounter = 0;
}
);
ID = 22;
Name = "EN Live";
totalNews = 3416;
}
);
};
}
My intent is to have a list of the articles (list of dictionaries) so that I can later access them easily. I have been stuck a while on this and my code is giving me an error about calling a non existent method for NSArray which has led me to suspect that I am misunderstanding the json object. I am totally new to this and any help is greatly appreciated.
Here's my code:
NSDictionary *results = [jsonString JSONValue];
NSDictionary *Articles = [[results objectForKey:#"Sections"] objectForKey:#"Section"];
NSArray *ListOfArticles = [Articles objectForKey:#"Article"];
for (NSDictionary *article in ListOfArticles)
{
NSString *title = [article objectForKey:#"Title"];
NSLog(title);
}
Thanks !
First of all, those aren’t valid JSON data. Names (in name/value pairs) are strings and must be quoted. String values must always be quoted. Boolean values must be either true or false (lowercase). Check http://json.org/ and http://www.ietf.org/rfc/rfc4627.txt?number=4627 and http://jsonlint.com
Here’s the structure of your data:
The top level value is an object (dictionary)
This object has a name (key) called Sections whose value is itself another object (dictionary)
Sections has a name (key) called Section whose value is an array
Each element in the Section array is an object (dictionary)
Each element in the Section array has a name (key) called Article whose value is an array, as well as other names (keys): ID, title, totalNews
Each element in the Article array is an object
If your JSON data were valid, you could parse them as follows:
// 1.
NSDictionary *results = [jsonString JSONValue];
// 2.
NSDictionary *sections = [results objectForKey:#"Sections"];
// 3.
NSArray *sectionsArray = [sections objectForKey:#"Section"];
// 4.
for (NSDictionary *section in sectionsArray) {
// 5.
NSLog(#"Section ID = %#", [section objectForKey:#"ID"];
NSLog(#"Section Title = %#", [section objectForKey:#"Title"];
NSArray *articles = [section objectForKey:#"Article"];
// 6.
for (NSDictionary *article in articles) {
NSLog(#"Article ID = %#", [article objectForKey:#"ID"];
NSLog(#"Article Title = %#", [article objectForKey:#"Title"];
// …
}
}
Your JSON framework is probably parsing out an NSDictionary where you're expecting an NSArray. It'll let you assign an NSDictionary to an NSArray, but then you'll get a runtime exception when you attempt to call a method on your "array". Judging by the JSON you posted (which isn't correct JSON), this is what I would have my parsing code look like. The names of the NSDictionaries and NSArrays are simply named after the JSON attributes they represent.
NSDictionary* results = [jsonString JSONValue];
NSDictionary* sections = [results valueForKey:#"Sections"];
NSArray* section = [sections valueForKey:#"Section"];
NSArray article = [[section objectAtIndex:0] valueForKey:#"Article"];
for (NSDictionary* anArticle in article) {
NSLog(#"%#", [anArticle valueForKey:#"Title"]);
}