1

How to calculate number of rows for each section and populate it's data. Below is the data.

 <__NSCFArray 0x7fadb3e73a60>(
    {
        AMID = "";
        AMName = "xyz";
        records =     (
                    {
                EId = 100;
                EMName = "abc";
                EName = "Ename1";
            }
        );
        EGroupId = 001;
        EGroupName = "SectionName1";
        stat = G;
    },

    {
        AMID = "";
        AMName = "zyx";
        records =     (
                    {
                EId = 144;
                EMName = "namename";
                EName = "somestring";
            },
                    {
                EId = 159;
                EMName = "somestring";
                EName = "somestring";
            },
                    {
                EId = 161;
                EMName = "somestring";
                EName = "somestring";
            }

    );
            EGroupId = 86;
            EGroupName = "SectionName2";
            stat = Y;
        }
)

From the above data, i want the "EGroupName" value in sections and dynamically count the numberofrowsinsection for each section(in this case, it's 'SectionName1 and SectionName2). Final output Should Be like,

**SectionName1**
    return 1;
**SectionName2**
    return 3;

really appreciate your help.

Edited

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

  NSString *selectedEngagementGroupId = engagementGroupDataArray[indexPath.section][@"EngagementGroupId"];
  NSString *selectedEngagementId = modelItem[@"EId"];
  NSLog(@"EGId %@",selectedEngagementGroupId);
  NSLog(@"EId %@",selectedEngagementId);

}
user3310076
  • 133
  • 12

2 Answers2

2

The array, once converted into objects will be an array of dictionaries, where each dictionary contains an array, and each contains a string value that can be used as a section name. That's a perfectly good datasource for a multi-section table view.

After parsing the JSON, you'll have an objective c collection, call it:

NSArray *parsedObject;

The number of sections is:

parsedObject.count;

The title of a section at an indexPath is:

parsedObject[indexPath.section][@"EGroupName"]

The number of rows in a section is:

NSArray *sectionArray = parsedObject[section][@"records"];
[sectionArray count]

The model item at a given indexPath is:

NSArray *sectionArray = parsedObject[indexPath.section][@"records"];
sectionArray[indexPath.row];

EDIT to go a little deeper, the section array itself is an array of dictionaries, so...

NSArray *sectionArray = parsedObject[indexPath.section][@"records"];
NSDictionary *modelItem = sectionArray[indexPath.row];

NSNumber *itemId = modelItem[@"EId"];
NSNumber *itemEMName = modelItem[@"EMName"];
NSNumber *itemName = modelItem[@"EName"];

// if the table cell is a just a vanilla UITableViewCell...
cell.textLabel.text = itemName;
cell.detailTextLabel.text = itemEMName;

EDIT AGAIN Remember, all of your datasource code must follow this pattern, so to get section level attributes from the data...

NSString *engagementGroupString = engagementGroupDataArray[section][@"EGroupName"];
NSString *engagementManagerString = engagementGroupDataArray[section][@"AMName"];

EDIT AGAIN, AGAIN You may find it tiresome to type all that stuff out to get the model item each time it's needed. If so, you can compress things by creating a helper function like:

- (NSDictionary *)modelItemForIndexPath:(NSIndexPath *):indexPath {
    NSArray *sectionArray = parsedObject[indexPath.section][@"records"];
    return sectionArray[indexPath.row];
}

Now, for example, when the user selects something:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *selectedEngagementGroupId = engagementGroupDataArray[indexPath.section][@"EngagementGroupId"];
    NSDictionary *modelItem = [self modelItemForIndexPath:indexPath];
    NSString *selectedEngagementId = modelItem[@"EId"];
    NSLog(@"EGId %@",selectedEngagementGroupId);
    NSLog(@"EId %@",selectedEngagementId);
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • I'm getting the correct number of rows for each section. How to display the "EName" as title and "EMName" as detailed for each row ? – user3310076 Jul 25 '16 at 15:55
  • @user3310076 - it appears from the data in the OP that the records array is an array of dictionaries, see edit for how to handle those. – danh Jul 25 '16 at 16:02
  • app is crashing while scrolling the table. Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (11) beyond bounds (11). I'll post my code in the answer box. Please let me know what i'm doing wrong. – user3310076 Jul 25 '16 at 17:20
  • On what line? Looking again at my suggestion, I'm pretty confident it is right. – danh Jul 25 '16 at 17:25
  • Probably should delete that post, since it isn't an answer. The viewForHeader code is wrong. It should use the same pattern for getting section data as I suggest above. See edit. – danh Jul 25 '16 at 17:46
  • Thank you so much danh. Working like charm. You helped me a lot. I have deleted the answer post and will mark your solution as answer. @Droppy - Thanks to you too for helping me out. Cheers – user3310076 Jul 25 '16 at 18:06
  • I have one more question, i'm getting the correct section(name, id, etc) but not the correct 'itemId' for the selected cell. How to retrieve the correct itemId of the selected cell ? I have pasted what i did in the edited section. – user3310076 Jul 27 '16 at 13:47
  • Your edit doesn't show an initialization for modelItem. – danh Jul 27 '16 at 14:48
  • I have declared modelItem as public dictionary and it is intialized in cellforrowatindexpath as given in your solution. Please let me know if I want to update the code – user3310076 Jul 27 '16 at 15:09
  • That's the mistake. By doing it that way, you're setting the modelItem to last one drawn, rather than the one pertinent to the indexPath given. Definitely, definitely, calculate a new modelItem each time you're passed an index path, and don't save it. – danh Jul 27 '16 at 15:11
  • Exactly the last item of row's value is retrieved for every cell I select. How to solve this problem ? I'm really lost actually – user3310076 Jul 27 '16 at 15:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118459/discussion-between-danh-and-user3310076). – danh Jul 27 '16 at 15:17
  • I tried using the helper method, now i'm able to get the correct 'itemId', but when there are two sections and app crashes when selecting second row of that particular section. Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (2) beyond bounds (2)' . I'll update the code – user3310076 Jul 27 '16 at 17:12
  • I'm out for next couple hours. but this might warrant an new question. feel free to compose one and post a link to it here – danh Jul 27 '16 at 17:23
  • thanks danh. It seems like working. Your helper method was working perfectly, just that i was doing some mistake. I corrected it and i'm getting all the values perfectly. I'll test throughly and let you know tomorrow. I really appreciate your commitment , Cheers !!! – user3310076 Jul 27 '16 at 17:28
  • Working as expected, Danh. Thanks again :) – user3310076 Jul 28 '16 at 08:06
1

I assume you know how to convert that JSON into an Objective-C collection (you will get a top-level array object I think; however you don't show the top-level object, which is not valid JSON).

You will need to create an NSMutableDictionary property to hold your data and the key will be the section name and the values will be the associated records array.

@property NSMutableDictionary *_sections;

However one complication is that dictionaries don't maintain order and order is very important with UITableView, so you need to hold the order in a separate array:

@property NSMutableArray *_sectionNames;

Allocate them in the bit of code that decode the JSON and then store data in them like this:

NSArray *arrayFromJson = ...;
for (NSDictionary *dict in arrayFromJson) {
    NSString *sectionName = dict[@"EGroupName"];
    [_sections setObject:dict[@"records"] forKey:sectionName];
    [_sectionNames addObject:sectionName];
}

If you want to sort the sections alphabetically, for example, then simply sort _sectionNames as you like (exercise for the reader).

And then the UITableDataSource methods will be something like this:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [_sectionNames count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSString *sectioName = _sectionNames[section];
    return [_sections[sectionName] count];
}
Droppy
  • 9,691
  • 1
  • 20
  • 27
  • Thanks. However, i'm getting "no visible @interface for nsmutabledictionary declares the selector addObject" error. and i have updated the actual data received from the webservice – user3310076 Jul 25 '16 at 14:52
  • I retracted the comment because the OP might have seen the error on the _sectionNames property, possibly declaring it as a dictionary rather than an array. I think your edit improves the answer, though. – danh Jul 25 '16 at 15:01
  • Though, the answer can be simplified by realizing that the parsed result will be an array of dictionaries, which -- without adding a sectionName array -- will suffice as the datasource. – danh Jul 25 '16 at 15:12