Reputation: 1430
I have to create a UITableView
using the JSON
response below ( Array ). I have no code for this yet but would love some direction to how i would split this array to accommodate categories and items on all levels.
{
"result":{
"products":[
{
"id":"4",
"product_code":"PR04",
"title":"Product1",
"franchisee_id":"118"
}
],
"categories":[
{
"id":"8",
"name":"Category1"
},
{
"id":"20",
"name":"Category2",
"products":[
{
"id":"9",
"product_code":"PR07",
"title":Product2,
"franchisee_id":"118"
}
]
}
]
}
}
I want to achieve the following result:
When a category is clicked it would slide to the products in that category. Would really love some direction on this. Some products will not be in categories. Like the example above.
Upvotes: 0
Views: 2293
Reputation: 8608
Well....
You need to parse the JSON file. You can easily google for some tutorials but here is a decent one.
Next you are going to need to setup a UITableView
to load the items. another good tutorial on UITableView
s
Then you are going to need to learn how to pass data between UIViewController
s. Tutorial.
So your steps in the code will be to:
UITableView
to display the top level elements. UITableViewController
to push to after a top level item has been selected. UITableViewController
so you can pass it relevant data from the first view controller where you parsed the JSON
. I'm assuming you were looking for a bunch of code on how to do this, but that's no fun :)
Let me know if you run into any troubles and I will be glad to help.
EDIT:
I know I said I wasn't going to dump code but I have some extra time.
Create an NSObject
subclass called ProductObject
and make the .h
look like this:
#import <Foundation/Foundation.h>
@interface ProductObject : NSObject
@property NSString *productCode, *productTitle, *franchiseId, *productId;
@end
Don't do any thing to the .m
Create another NSObject
subclass called CategoryObject
and make the .h
look like this:
#import <Foundation/Foundation.h>
@interface CategoryObject : NSObject
@property NSString *categoryName, *categoryId;
@property NSArray *products;
@end
Again, don't need to do anything to the .m
.
Now, in the class that you want to display the UITableView
will the Products and Categories (this is all in the .m
, the .h
is empty):
#import "ViewController.h"
#import "CategoryObject.h"
#import "ProductObject.h"
@interface ViewController ()
//Hooked in from IB
@property (weak, nonatomic) IBOutlet UITableView *table;
//Our UITableView data source
@property NSMutableDictionary *tableObjects;
@end
@implementation ViewController
/**
Parses a the local JSON file
*/
- (void)parseJSON {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"json"];
//création d'un string avec le contenu du JSON
NSString *myJSON = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
NSError *error;
NSDictionary *topLevleJSON = [NSJSONSerialization JSONObjectWithData:[myJSON dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
if (error) {
NSLog(@"Error serializing JSON: %@", error.localizedDescription);
return;
}
NSArray *products = topLevleJSON[@"products"];
NSArray *categories = topLevleJSON[@"categories"];
//Use a NSDictonary so that it contains an NSArray of ProductObjects for the "Products" key, and an array of CategoryObjects for the "Category" key.
self.tableObjects = [NSMutableDictionary new];
//Parse all the products
NSMutableArray *productsInJSON = [NSMutableArray new];
[products enumerateObjectsUsingBlock:^(NSDictionary *productObject, NSUInteger idx, BOOL *stop) {
ProductObject *product = [self createProductObjectFromDictionary:productObject];
[productsInJSON addObject:product];
}];
//Set the array of ProductObjects for the key @"Products"
[self.tableObjects setObject:productsInJSON forKey:@"Products"];
//Parse all the categories
NSMutableArray *categoriesInJSON = [NSMutableArray new];
[categories enumerateObjectsUsingBlock:^(NSDictionary *categoryObject, NSUInteger idx, BOOL *stop) {
CategoryObject *category = [self createCategoryObjectFromDictionary:categoryObject];
[categoriesInJSON addObject:category];
}];
//Set the array of CategoryObjects for key @"Categories"
[self.tableObjects setObject:categoriesInJSON forKey:@"Categories"];
[self.table reloadData];
}
/**
Creates a ProductObject from an NSDictonary.
@param dictionary The dictonary describing the Product parsed from JSON
@return A pretty formatted ProductObject
*/
- (ProductObject*)createProductObjectFromDictionary:(NSDictionary*)dictionary {
ProductObject *product = [ProductObject new];
product.productTitle = dictionary[@"title"];
product.productCode = dictionary[@"product_code"];
product.franchiseId = dictionary[@"franchisee_id"];
product.productId = dictionary[@"id"];
return product;
}
/**
Creates a Category from an NSDictionary
@param dictionary The dictonary describing the Category parsed from JSON
@return A pretty formatted CategoryObject
*/
- (CategoryObject*)createCategoryObjectFromDictionary:(NSDictionary*)dictionary {
CategoryObject *category = [CategoryObject new];
category.categoryId = dictionary[@"id"];
category.categoryName = dictionary[@"name"];
//Check to see if the "products" key exist for the category, if we don't check and just look for it, we will get a crash if it doesn't exist.
if ([[dictionary allKeys] containsObject:@"products"]) {
NSArray *categoryProducts = dictionary[@"products"];
//Parse all the Products for the Category.
NSMutableArray *categoryProductsFormatted = [NSMutableArray new];
[categoryProducts enumerateObjectsUsingBlock:^(NSDictionary *productObject, NSUInteger idx, BOOL *stop) {
ProductObject *product = [self createProductObjectFromDictionary:productObject];
[categoryProductsFormatted addObject:product];
}];
category.products = [NSArray arrayWithArray:categoryProductsFormatted];
}
else {
category.products = nil;
}
return category;
}
#pragma mark -
#pragma mark - UITableView delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.tableObjects allKeys] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//Get the key for this section
NSString *key = [[self.tableObjects allKeys] objectAtIndex:section];
//Return the number of objects for this key.
return [(NSArray*)[self.tableObjects objectForKey:key] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[self.tableObjects allKeys] objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellIdentifier"];
}
//Get all the NSArray associated with this section, which will be an array of ProductObjects or an array of CategoryObjects
NSString *key = [[self.tableObjects allKeys] objectAtIndex:indexPath.section];
NSArray *sectionobjects = (NSArray*)[self.tableObjects objectForKey:key];
id object = [sectionobjects objectAtIndex:indexPath.row];
//Set the cell text based on what kind of object is returned
if ([object isKindOfClass:[ProductObject class]]) {
cell.textLabel.text = [(ProductObject*)object productTitle];
}
else if ([object isKindOfClass:[CategoryObject class]]) {
cell.textLabel.text = [(CategoryObject*)object categoryName];
}
return cell;
}
#pragma mark -
#pragma mark - UITableView delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSString *key = [[self.tableObjects allKeys] objectAtIndex:indexPath.section];
NSArray *sectionobjects = (NSArray*)[self.tableObjects objectForKey:key];
id object = [sectionobjects objectAtIndex:indexPath.row];
//They selected a product
if ([object isKindOfClass:[ProductObject class]]) {
ProductObject *product = (ProductObject*)object;
NSLog(@"%@", product.productTitle);
NSLog(@"%@", product.productCode);
NSLog(@"%@", product.productId);
}
//They selected a Category
else if ([object isKindOfClass:[CategoryObject class]]) {
//Check to see if the CategoryObject has any ProductObjects associated with it
if ([(CategoryObject*)object products]) {
//Now you will need to pass array of ProductObjects this along to your next view controller.
NSArray *cateogryProducts = [(CategoryObject*)object products];
//For demonstration purposes, i'll run through and print out all the Products for this Category
[cateogryProducts enumerateObjectsUsingBlock:^(ProductObject *product, NSUInteger idx, BOOL *stop) {
NSLog(@"%@", product.productTitle);
NSLog(@"%@", product.productCode);
NSLog(@"%@", product.productId);
}];
}
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Start parsing the JSON
[self parseJSON];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
EDIT:
If you are wanting to open and close parts of the table like an accordion, take a look at Apple's same code: Table View Animations and Gestures.
Upvotes: 3