Maintain order of elements of NSMutableDictionary [duplicate] - ios

This question already has answers here:
Maintaining the order while iterating a NSDictionary
(3 answers)
Closed 3 years ago.
I am getting a dictionary of the following format :
[
{
"position": "1",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
},
{
"position": "2",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
},
{
"position": "1",
"name": "Jaen",
"group": "Teacher",
"Address": "Delhi"
}
]
Basically, I want to group them around the key named "group".I have to create a dictionary in the following format to populate data in my UI.
[
{
"Student": [
{
"position": "1",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
},
{
"position": "2",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
}
],
"Teacher": [
{
"position": "1",
"name": "Jaen",
"group": "Teacher",
"Address": "Delhi"
}
]
}
]
the order of the Groups should be maintained ie Student should come before Teacher. But when I am printing dictGroupField it is giving random results in terms of order.
How can i maintain the order?
Please find the code below that I was using :
#property (strong, nonatomic) NSMutableDictionary *dictGroupField;
-(void)loadFieldData {
_dictGroupField = [[NSMutableDictionary alloc] init];
NSMutableArray *arrayFields = [self getArrayFields];
for (NSDictionary *dictT in arrayFields) {
NSString *strGroup = [dict valueForKey:#"group"];
if ([_dictGroupField valueForKey:strGroup] == nil) {
NSMutableArray *arrGroup = [[NSMutableArray alloc] init];
[arrGroup addObject:dict];
[_dictGroupField setObject:arrGroup forKey:strGroup];
} else {
NSMutableArray *arrGroupExist = [_dictGroupField valueForKey:strGroup];
[arrGroupExist addObject:dict];
[_dictGroupField setObject:arrGroupExist forKey:strGroup];
}
}
}

You can't maintain it order. Dictionaries are unordered collections of key-value associations. See more Docs

Related

how to parse complex json data in iOS?

I am new to iOS and I want to parse data but it is so complex, I don't know how to parse it. Below given is the json data.
{
"response_code": 200,
"last_updated": {
"date": "2015-12-27",
"time": "01:32:13"
},
"trains": [
{
"train": {
"number": "04921",
"start_time": "04:45",
"name": "SRE-UMB MEMU SPECIAL",
"type": "HSP"
},
"dest": {
"code": "UMB",
"name": "AMBALA CANT JN"
},
"source": {
"code": "SRE",
"name": "SAHARANPUR"
}
},
{
"train": {
"number": "04922",
"start_time": "20:45",
"name": "UMB-SRE MEMU SPECIAL",
"type": "HSP"
},
"dest": {
"code": "SRE",
"name": "SAHARANPUR"
},
"source": {
"code": "UMB",
"name": "AMBALA CANT JN"
}
}
]
}
{ , , } - it's a dictionary
[ , , ] - it's an array
In your case you get:
First level - dictionary with keys response_code, last_updated, trains.
Where:
response_code - value
last_updated - dictionary with keys date, time
trains - array of dictionaries with keys train, dest, source
etc.
Use the NSJSONSerialization class, it's easy.
For example, in Objective-C:
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (jsonObject) {
// jsonObject is an NSArray or NSDictionary representation of the data that you can now do something with
}

iOS JSON Parsing, array with multiple array

I have a JSON array with multiple object and I don't know how do I grab the "url" tag as an NSArray or a NSDictionary and show that image url in Tableview. I can't change the JSON data format.How should I do this?
Here is what the JSON response looks like:
{
"meta": {
"total_count": 10
},
"pages": [
{
"id": 7,
"meta": {
"type": "dashboard.NewsEvents",
"detail_url": "http://suno.to/api/v1/pages/7/"
},
"title": "NoEvent",
"created_at": "2016-03-06T10:42:19.646000Z",
"cover_url": [
[
{
"url": "/media/images/Maha_Shivratri2.original.jpg",
"title": "Maha Shivratri2.jpg"
},
{
"url": "/media/images/Maha_Shivratri1.original.jpg",
"title": "Maha Shivratri1.jpg"
}
],
[
{
"url": "/media/images/Celebrations.original.jpg",
"title": "Celebrations.jpg"
},
{
"url": "/media/images/Crew.original.jpg",
"title": "Crew.jpg"
},
{
"url": "/media/images/World_record.original.jpg",
"title": "World record.jpg"
},
{
"url": "/media/images/AI_pilots.original.jpg",
"title": "AI pilots.jpg"
}
],
[
{
"url": "/media/images/CbVv-VbWEAAmwv_.original.jpg",
"title": "DAL SWARAJ YATRA"
},
{
"url": "/media/images/CbVv_-TWwAE7RjM.original.jpg",
"title": "DAL SWARAJ YATRA"
},
{
"url": "/media/images/CbVv_SmXIAALQP8.original.jpg",
"title": "DAL SWARAJ YATRA"
},
{
"url": "/media/images/CahEc--UkAArc_z.original.jpg",
"title": "DAL SWARAJ YATRA"
}
]
]
},
{
"id": 2530,
"meta": {
"type": "dashboard.NewsEvents",
"detail_url": "http://suno.to/api/v1/pages/2530/"
},
"title": "World Culture Festival",
"created_at": "2016-03-12T06:59:21.023000Z",
"cover_url": [
[
{
"url": "/media/images/Security.original.jpg",
"title": "Security check"
}
],
[
{
"url": "/media/images/Elephant_statues.original.jpg",
"title": "Elephant"
}
],
[
{
"url": "/media/images/6.original.jpg",
"title": "Stage"
},
{
"url": "/media/images/4.original.jpg",
"title": "Stage"
}
]
]
},
{
"id": 2675,
"meta": {
"type": "dashboard.NewsEvents",
"detail_url": "http://suno.to/api/v1/pages/2675/"
},
"title": "Holi in Barsana",
"created_at": "2016-03-17T12:35:09.308000Z",
"cover_url": [
[
{
"url": "/media/images/Brajwasi_playing_holi_.original.jpg",
"title": "Holi in Barsana"
},
{
"url": "/media/images/dancing_.original.jpg",
"title": "Holi in Barsana"
},
{
"url": "/media/images/holi.._.original.jpg",
"title": "Holi in Barsana"
},
{
"url": "/media/images/holi..._.original.jpg",
"title": "Holi in Barsana"
}
],
[
{
"url": "/media/images/Lathmar_holi_19_n54f7LJ.original.jpg",
"title": "Lathmar Holi in Barsana"
}
],
[
{
"url": "/media/images/Lathmar_holi_17.original.jpg",
"title": "Lathmar Holi in Barsana"
},
{
"url": "/media/images/Lathmar_holi_20.original.jpg",
"title": "Lathmar Holi in Barsana"
}
]
]
},
I'm using this code to get the "url" array. Plz correct me ?
NSArray *imageUrlArray = [[self.jsonData objectAtIndex:indexPath.row]objectForKey:#"cover_url"];
NSLog(#"IMAGE URL ARRAY:%#",imageUrlArray);
NSString *imageUrl = [imageUrlArray valueForKey:#"url"];
NSLog(#"IMAGE URL:%#",imageUrl);
To view the JSON structure - http://jsonviewer.stack.hu/
NSMutableArray* imageurlArray = [NSMutableArray new];
NSArray* jsonArray = jsonData[#"pages"];
for (int i = 0; i<[jsonArray count]; i++) {
NSArray* coverUrlArray = jsonArray[i][#"cover_url"];
for (int t = 0; t< [coverUrlArray count]; t++) {
NSArray* UrlArray = coverUrlArray[t];
for (int x = 0; x<[UrlArray count]; x++) {
[imageurlArray addObject:UrlArray[x][#"url"]];
}
}
}
NSLog(#"imageurlArray: %#", imageurlArray);
//imageurlArray contains all url
//In cell for row at indexpath --> use imageurlArray[indexPath.row];
You have array wrappped by another array.
So, use this direction:
NSDictionary *json=//..initialized
NSArray *pages = [json valueForKey#"pages"];
NSDictionary *page = [pages objectAtIndex:0];
NSArray *ar1 = [page valueForKey#"cover_url"];
NSArray *ar2 = [ar1 objectAtIndex:0];
NSDictionary *elem = [ar2 objectAtIndex:0];
NSString *value = [elem valueForKey#"url"];
I would suggest using Mantel or JSONModel libraries for parsing objects and having decent DTOs.
When you deal with something like this, i suggest putting the complete json in http://jsonviewer.stack.hu/ so you can see the correct structure without getting confused.
Then it's just a matter of digging. When you see { }, you add a dictionary, when you see [ ], you add an array, until you reach your url object :)
I'm not writing the code because it is pretty trivial, just a mix of objectForKeys for dictionaries and objectAtIndex for arrays.
The last layers are just objects, so they're handled like any other object.
If you're confused about json, I suggest you try giving your json-parser a simple json (you hard core it yourself just above, its really just for testing).
Small advice :
Give it a simple array of 1 object, then 2, then put the array in a dict, then two, etc. and you keep making the json more complex until you really understand how it works. Then you'll eventually have a fake json just like your real one, and you can remove the fake and use the real one :)
Other advice :
There are many json parsing libraries that let you create the object model, where you can create (for example) a Page object that has an ID, a title, a cover URl, etc. that matches the JSON structure, and then you just tell the parser " make that JSON a Page!" and voilà, you have a Page. I don't know any of those json libraries in ios, but people will surely link it here, so try it out ! They're super easy to use and make json parsing really straightforward. And also, you don't have to map everything manually like you're doing ;)

Pulling Data from an NSDictionary

So I have an NSDictionary that has a variety of data within it. When printed to the log, it prints like this:
[{"user_id":3016817,"grade":"A","percent":"93","grading_periods":[{"assignments":[{"points":100.0,"grade":"A","score":95.0,"percent":"93","comment":null,"id":3268180},{"points":100.0,"grade":"A","score":90.0,"percent":"93","comment":null,"id":3268181}],"grade":"A","percent":"93","name":"Default"}]},{"user_id":3016818,"grade":"A","percent":"94","grading_periods":[{"assignments":[{"points":100.0,"grade":"A","score":92.0,"percent":"94","comment":null,"id":3268180},{"points":100.0,"grade":"A","score":95.0,"percent":"94","comment":null,"id":3268181}],"grade":"A","percent":"94","name":"Default"}]}]
If I use a formatter online, its a lot more readable and looks something like this:
[
{
"user_id": 3016817,
"grade": "A",
"percent": "93",
"grading_periods": [
{
"assignments": [
{
"points": 100,
"grade": "A",
"score": 95,
"percent": "93",
"comment": null,
"id": 3268180
},
{
"points": 100,
"grade": "A",
"score": 90,
"percent": "93",
"comment": null,
"id": 3268181
}
],
"grade": "A",
"percent": "93",
"name": "Default"
}
]
},
{
"user_id": 3016818,
"grade": "A",
"percent": "94",
"grading_periods": [
{
"assignments": [
{
"points": 100,
"grade": "A",
"score": 92,
"percent": "94",
"comment": null,
"id": 3268180
},
{
"points": 100,
"grade": "A",
"score": 95,
"percent": "94",
"comment": null,
"id": 3268181
}
],
"grade": "A",
"percent": "94",
"name": "Default"
}
]
}
]
My question would be how would I access the value of grade or score for a specific user_id using this dictionary?
Your string represents a NSArray, not a NSDictionary. And it's a JSON string, so you can parse it using NSJSONSerialization:
NSString *jsonString = #"..." // your string here
// Create array from json string
NSArray *jsonArray = [NSJSONSerialization
JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:Nil];
// Loop to find your user_id
// Because each child of this array is a dictionary
for (NSDictionary *dic in jsonArray) {
if ([dic[#"user_id"] isEqual:#3016817]) { // user_id field is number
// Access what you want
NSString *grade = dic[#"grade"];
// For "score" you must go deeper
// Just remember, [] is array and {} is dictionary
}
}
A simple way to do this would be
for (NSDictionary* d in theArray) {
if ([d[#"user_id"] isEqualToString: u]) {
// do something
}
}
And matt is right, it is an array of dictionaries, no matter what type you declared to be.
You can use below class method of NSJsonSerialization class to create NSArray which will contain all the dictionaries.
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
Once you get the array of dictionaries from JSON, you can do following:
NSArray *filteredjsonArr = [jsonArr filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"user_id == %#", #"3016818"]];
NSDictionary *dict = [filtered firstObject];
if (dict != nil) {
NSString *grade = [dict objectForKey:#"grade"];
NSArray *gradingPeriods = [dict objectForKey:#"grading_periods"];
}
To access score and grade for specific assignments, you'll need to drill down further into gradingPeriods array.

Can't get NSArray of Custom Class to display on cellForRowAtIndexPath:

All, I'm losing my mind. I have a class with the following code passing an NSArray of "Events" to my View Controller:
+ (NSArray *)eventsFromJSON:(NSData *)objectNotation error:(NSError **)error {
NSError *localError = nil;
NSArray *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
if (localError != nil) {
*error = localError;
return nil;
}
NSMutableArray *events = [[NSMutableArray alloc] init];
//NSArray *results = [parsedObject valueForKey:#"results"];
NSLog(#"Count %lu", (unsigned long)parsedObject.count);
for (NSDictionary *eventDic in parsedObject) {
Event *event = [[Event alloc] init];
for (NSString *key in eventDic) {
if ([event respondsToSelector:NSSelectorFromString(key)]) {
[event setValue:[eventDic valueForKey:key] forKey:key];
}
}
[events addObject:event];
}
return events;
}
On my view controller I've got the following code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"eventCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
Event *event = [self.eventData objectAtIndex:indexPath.row];
cell.textLabel.text = event.title;
cell.detailTextLabel.text = event.link;
return cell;
}
- (void) didReceiveEvents:(NSArray *)events {
self.eventData = [events copy];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
A sample of the JSON I'm parsing is below:
[
{
"ID": 576,
"title": “Event Title“,
"status": "publish",
"type": "tribe_events",
"author": {
"ID": 1,
"username": "admin",
"name": "admin",
"first_name": “Name”,
"last_name": “Last”,
"nickname": "admin",
"slug": "admin",
"URL": "",
"avatar": "1.gravatar.com/avatar/",
"description": "",
"registered": "-001-11-30T00:00:00+00:00",
"meta": {
"links": {
"self": "url.com/wp-json/users/1",
"archives": "url.com/wp-json/users/1/posts"
}
}
},
"content": "<p>Join us if you are interested.</p>\n",
"parent": {
"ID": 575,
"title": “Title”,
"status": "publish",
"type": "tribe_events",
"author": {
"ID": 1,
"username": "admin",
"name": "admin",
"first_name": “First”,
"last_name": “Last”,
"nickname": "admin",
"slug": "admin",
"URL": "",
"avatar": "1.gravatar.com/avatar/?s=96",
"description": "",
"registered": "-001-11-30T00:00:00+00:00",
"meta": {
"links": {
"self": "url.com/wp-json/users/1",
"archives": "url.com/wp-json/users/1/posts"
}
}
},
"content": "<p>Join us if you are interested in joining </p>\n",
"parent": 0,
"link": "url.com/calendar/worship-service-practice/2014-12-06/",
"date": "2014-12-04T20:09:21-06:00",
"modified": "2014-12-04T20:09:21-06:00",
"format": "standard",
"slug": "worship-service-practice",
"guid": "url.com/?post_type=tribe_events&p=575",
"excerpt": "<p>Join us if you are interested i</p>\n",
"menu_order": 0,
"comment_status": "closed",
"ping_status": "closed",
"sticky": false,
"date_tz": "America/Chicago",
"date_gmt": "2014-12-05T02:09:21+00:00",
"modified_tz": "America/Chicago",
"modified_gmt": "2014-12-05T02:09:21+00:00",
"meta": {
"links": {
"self": "url.com/wp-json/posts/575",
"author": "url.com/wp-json/users/1",
"collection": "url.com/wp-json/posts",
"replies": "url.com/wp-json/posts/575/comments",
"version-history": "url.com/wp-json/posts/575/revisions"
}
},
"post_meta": {
"EventStartDate": "2014-12-06 08:00:00",
"EventEndDate": "2014-12-06 09:00:00"
},
"featured_image": null,
"terms": {
"tribe_events_cat": [
{
"ID": 13,
"name": "Community Outreach",
"slug": "community-outreach",
"description": "",
"parent": null,
"count": 52,
"link": "url.com/calendar/category/community-outreach/",
"meta": {
"links": {
"collection": "url.com/wp-json/taxonomies/tribe_events_cat/terms",
"self": "url.com/wp-json/taxonomies/tribe_events_cat/terms/9"
}
}
}
]
}
},
"link": "url.com/calendar/worship-service-practice/2014-12-13/",
"date": "2014-12-04T20:09:21-06:00",
"modified": "2014-12-04T20:09:21-06:00",
"format": "standard",
"slug": "worship-service-practice-2014-12-13",
"guid": "url.com/?post_type=tribe_events&eventDate=2014-12-13#038;p=575",
"excerpt": "<p>Join us if you are interested </p>\n",
"menu_order": 0,
"comment_status": "closed",
"ping_status": "closed",
"sticky": false,
"date_tz": "America/Chicago",
"date_gmt": "2014-12-05T02:09:21+00:00",
"modified_tz": "America/Chicago",
"modified_gmt": "2014-12-05T02:09:21+00:00",
"meta": {
"links": {
"self": "url.com/wp-json/posts/576",
"author": "url.com/wp-json/users/1",
"collection": "url.com/wp-json/posts",
"replies": "url.com/wp-json/posts/576/comments",
"version-history": "url.com/wp-json/posts/576/revisions",
"up": "url.com/wp-json/posts/575"
}
},
"post_meta": {
"EventStartDate": "2014-12-13 08:00:00",
"EventEndDate": "2014-12-13 09:00:00"
},
"featured_image": null,
"terms": {
"tribe_events_cat": [
{
"ID": 13,
"name": "Community Outreach",
"slug": "community-outreach",
"description": "",
"parent": null,
"count": 52,
"link": "url.com/calendar/category/community-outreach/",
"meta": {
"links": {
"collection": "url.com/wp-json/taxonomies/tribe_events_cat/terms",
"self": "url.com/wp-json/taxonomies/tribe_events_cat/terms/9"
}
}
}
]
}
},
{…
I can't for the life of me get the data from the Event class to display on the table. I have 10 empty rows display on the table with the disclosure indicator but no text. When I throw an NSLog into the cellForRowAtIndexPath function and attempt to print event.title it logs as null. Any ideas on what I'm doing wrong?
You never set event.title. Also the way you iterate through the json is incorrect. If it is a property you should set it like so:
for(NSDictionary *eventDic in [parsedObject objectForKey:#"results"]){
Event *event = [[Event alloc] init];
event.title = eventDic[#"title"]; //shorthand for [eventDic objectForKey:#"title"];
event.link = eventDic[#"link"];
[events addObject:event];
}
It turns out my code was fine, but when I setup my Event class I made the attributes weak vs strong. Once making the properties attributes strong, it retained all of the pointers just fine and everything was good to go.

Parsing Json to get all the contents in one NSArray

That's the content...
[
{
"id": "",
"title": "",
"website": "",
"categories": [
{
"id": "",
"label": ""
}
],
"updated":
},
{
"id": "",
"title": "",
"website": "",
"categories": [
{
"id": "",
"label": ""
}
],
"updated":
}
]
How can I insert every feed source in one array?
NSDictionary *results = [string JSONValue];
NSArray *subs = [results valueForKey:#"KEY"];
Which key I must insert?
THanks
as I can see your structure, you will get out of this JSON-String
NSArray:
[
NSDictionary:
{
NSString: "id",
NSString: "title",
NSString: "website",
NSArray: "categories":
[
NSDictionary:
{
NSString: "id",
NSString: "label"
}
],
NSNumber: "updated"
},
NSDictionary:
{
...
}
]
So you have already an array of "Feeds" at root and you have to itterate them with their index in the array with. For first id i.e. [[myJsonStructure objectAtIndex:0] objectForKey:#"id"];

Resources