Search code examples
iosiphonejsonipaduisplitviewcontroller

iOS - DetailViewController not displaying multiple entries/values from JSON


I'm creating a simple iPad app with DetailViewController. Everything works great, but when I try to use multiple level JSON, it doesn't work anymore the app crashes.

I retrieve and loop through data:

-(void) retrieveData{

    NSURL * url = [NSURL URLWithString:getDataURL];
    NSData * data = [NSData dataWithContentsOfURL:url];

    jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

    fruitArray = [[NSMutableArray alloc] init];

    //loop through jsonarray
    for(int i =0;i < jsonArray.count;i++){

        NSString * cName = [[jsonArray objectAtIndex:i] valueForKey:@"cityName"];
        NSString * cFruit = [[jsonArray objectAtIndex:i] valueForKey:@"fruit"];

        //add object to fruitArray array
        [fruitArray addObject:[[Fruits alloc]initWithCityDocumentName:cName andFruit:cFruit]];

    }
    //reload table view
    [self.tableView reloadData];
}

using json:

[{
    "id": "1",
    "cityName": "London",
    "fruit":"Apple"
}, {
    "id": "2",
    "cityName": "Berlin",
    "fruit":"Pear"
}]

and then I set the labels(I hook them up from the storyboard/NIB):

- (void)setLabels{
    cityNameLabel.text = currentCity.documentName;
    fruitLabel.text = currentCity.documentFruit;
}

All this above work fine.

But as soon as I create multiple values in the JSON for fruits, it does not work! New JSON:

[{
    "id": "1",
    "cityName": "London",
    "fruit":
        ["Apple", "Pear", "Orange", "Lemon"]
}, {
    "id": "2",
    "cityName": "Berlin",
    "fruit":
        ["Mango", "Melon", "Tomatoe", "Avocado"]
}]

It looks to me that I need to somehow programatically create the labels and loop over them? Basically, I need to see multiple values in the Detail View Controller for each id How can I do it?

I really need a help here :( Thank you.

EDIT: I was now able to create an Array rather than strings but When I'm creating buttons from them it won't let me add the title based on what's in array:

NSMutableArray * cFruit = [[jsonArray objectAtIndex:i] valueForKey:@"fruit"];

and then:

- (void)setLabels{


        for(int i=0;i<=currentCity.documentFruit.count;i++){

        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

        [button addTarget:self
                   action:@selector(setLabels)
         forControlEvents:UIControlEventTouchUpInside];
        //below is my error - looks like it doesn't like setting the titles from array
        [button setTitle:[currentCity.documentFruit objectAtIndex:i] forState:UIControlStateNormal];

        button.frame = CGRectMake(20.0, ButtonHeightPlusOffsetBetweenButtons * i , 280.0, 40.0);

        //Set Tag for future identification
        [button setTag:i];

        [self.view addSubview:button];

    }
    }

Solution

  • Here I am providing you complete code, to do so

    #import "ViewController.h"
    #import "FruitsBO.h"
    
    @interface ViewController ()
    
    @property (strong, nonatomic) IBOutlet UITableView *tblFruit;
    @property (nonatomic, strong) NSMutableArray *arrFruitData;
    @end
    
    @implementation ViewController
    @synthesize arrFruitData;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        arrFruitData = [[NSMutableArray alloc] init];
        [self loadLocalJson];
    }
    
    
    -(void)loadLocalJson
    {
        NSString *pathStringToLocalFile = [[NSBundle mainBundle] pathForResource:@"Fruit" ofType:@"json"];
    
        NSError *deserializingError;
        NSURL *localFileURL = [NSURL fileURLWithPath:pathStringToLocalFile];
        NSData *contentOfLocalFile = [NSData dataWithContentsOfURL:localFileURL];
        NSArray *objects = [NSJSONSerialization JSONObjectWithData:contentOfLocalFile
                                                    options:NSJSONReadingAllowFragments
                                                      error:&deserializingError];
    
        [self parseFruit:objects];
    }
    
    
    -(void)parseFruit:(NSArray *)arrFruits
    {
    
        for (NSDictionary *dictTemp in arrFruits) {
            FruitsBO *fruit = [[FruitsBO alloc] init];
    
            fruit.fruitID = [dictTemp objectForKey:@"id"];
            fruit.cityName = [dictTemp objectForKey:@"cityName"];
            fruit.arrFruit = [dictTemp objectForKey:@"fruit"];
    
            [arrFruitData addObject:fruit];
            fruit = nil;
        }
    
        [self.tblFruit reloadData];
    }
    
    #pragma mark - TableView Delegate -
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return [self.arrFruitData count];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        FruitsBO *obj = [self.arrFruitData objectAtIndex:section];
        return [obj.arrFruit count];
    }
    
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return 50;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    {
        return 30;
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        FruitsBO *obj = [self.arrFruitData objectAtIndex:section];
        return obj.cityName;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *simpleTableIdentifier = @"fruitIdentifier";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
        }
    
        FruitsBO *objTemp = [self.arrFruitData objectAtIndex:indexPath.section];
    
        cell.textLabel.text = [objTemp.arrFruit objectAtIndex:indexPath.row];
    
        return cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    

    Here my Json

     [{
      "id": "1",
      "cityName": "London",
      "fruit":
      ["Apple", "Pear", "Orange", "Lemon"]
      }, {
      "id": "2",
      "cityName": "Berlin",
      "fruit":
      ["Mango", "Melon", "Tomatoe", "Avocado"]
      },{
      "id": "2",
      "cityName": "Austin",
      "fruit":
      ["Mango"]
      }]
    

    Here my output

    Output