Search code examples
iphoneobjective-ciosjsonjson-framework

Sectioned UITable & JSON


I have been trying for days to figure out how to parse this JSON to a sectioned UITable but I am not successful, I've only been able to figure out how to get the section name, but failed to get each section row count and data for each row in each section.

Since the transportation group may vary from time to time and their name may change, so I guess I need to use allKeys to find out each section title 1st.

Please help and points me to the right direction to extract the data for a sectioned UITable, Thank you.

{
   "transport" : {
  "public" : [
     {
        "transport_id" : "2",
        "transport_name" : "Ferry"
     },
     {
        "transport_id" : "3",
        "transport_name" : "Bus"
     },
     {
        "transport_id" : "4",
        "transport_name" : "Taxi"
     },
     {
        "transport_id" : "5",
        "transport_name" : "Tram"
     }
  ],
  "Private" : [
     {
        "transport_id" : "11",
        "transport_name" : "Bicycle"
     },
     {
        "transport_id" : "12",
        "transport_name" : "Private Car"
     }
  ],
  "Misc" : [
     {
        "transport_id" : "6",
        "transport_name" : "By Foot"
     },
     {
        "transport_id" : "7",
        "transport_name" : "Helicopter"
     },
     {
        "transport_id" : "8",
        "transport_name" : "Yatch"
     }
  ]
   }
}  



NSDictionary *results = [jsonString JSONValue];

NSDictionary *all = [results objectForKey:@"transport"];
NSArray *allKeys = [all allKeys];

NSArray *transports = [results objectForKey:@"transport"];
for (NSDictionary *transport in transports)
{
    [transportSectionTitle addObject:(transport)];
}


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

Solution

  • The easiest solution to explain is to use the all dictionary as your datasource.

    NSDictionary *results = [jsonString JSONValue];
    
    NSDictionary *all = [results objectForKey:@"transport"];
    
    // self.datasource would be a NSDictionary retained property
    self.datasource = all;
    

    Then to get the number of sections you could do :

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return [self.datasource count]; // You can use count on a NSDictionary
    }
    

    To get the title of the sections:

    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    
        NSString *title = [[self.datasource allKeys] objectAtIndex:section];
    
        return title;
    }
    

    To get the number of rows in each section:

    - (NSInteger)tableView:(UITableView *)favTableView numberOfRowsInSection:(NSInteger)section {
    
        // Get the all the transports
        NSArray *allTransports = [self.datasource allValues];
    
        // Get the array of transports for the wanted section
        NSArray *sectionTransports = [allTransports objectAtIndex:section];
    
        return [sectionTransports count];
    }
    

    Then to get the rows :

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
         static NSString *CellIdentifier = @"Cell";
    
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
         if (cell == nil) {
             cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
         }
    
         // Get the all the transports
         NSArray *allTransports = [self.datasource allValues];
    
         // Get the array of transports for the wanted section
         NSArray *sectionTransports = [allTransports objectAtIndex:indexPath.section];
    
         // Then get the transport for the row
         NSDictionary *transport = [sectionTransports objectAtIndex:indexPath.row];
    
         // Now you can get the name and id of the transport
         NSString *tansportName = [transport objectForKey:@"transport_name"];
         NSString *transportId = [transport objectForKey:@"transport_id"];
    
         NSString *transportDescription = [NSString stringWithFormat:@"%@ - %@",transportId, transportName];
    
         cell.textLabel.text = transportDescription;
    
         return cell;
     }
    

    That's the gist of it anyway.

    You might want to store the allKeys and allValues arrays as class properties instead of having to go through them in all the tableview's delegate and datasource methods, but you should have all the info to build yuor table now.

    Hope this helps :)