【问题标题】:iOS - DetailViewController not displaying multiple entries/values from JSONiOS - DetailViewController 不显示来自 JSON 的多个条目/值
【发布时间】:2014-12-16 12:30:31
【问题描述】:

我正在使用 DetailViewController 创建一个简单的 iPad 应用程序。一切都很好,但是当我尝试使用多级 JSON 时,它不再工作了,应用程序崩溃了。

我检索并循环遍历数据:

-(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];
}

使用 json:

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

然后我设置标签(我从情节提要/NIB 中将它们连接起来):

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

以上所有这些都可以正常工作。

但是,一旦我在 JSON 中为水果创建了多个值,它就不起作用了! 新 JSON:

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

在我看来,我需要以某种方式以编程方式创建标签并循环它们?基本上,我需要在详细视图控制器中查看每个 id 的多个值 我该怎么做?

我真的需要帮助 :( 谢谢。

编辑:我现在能够创建一个数组而不是字符串,但是当我从它们创建按钮时,它不会让我根据数组中的内容添加标题:

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

然后:

- (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];

    }
    }

【问题讨论】:

  • 您将数组分配给字符串变量,然后将其用作字符串。取变量为id类型,然后检查变量的类,如果是字符串(表示水果键包含单个水果)则执行当前代码,如果是数组,则设法检索。
  • 是的,你是对的。但是如何使用这个新数组来创建多个标签或文本字段?
  • 您需要以编程方式创建标签或文本字段,以使其数量动态。使用循环根据您的水果数组计数创建它们
  • 你能帮我怎么做吗?
  • @angular_learner 为什么要以编程方式创建文本字段?如果您只想显示值,请使用 UITableView

标签: ios iphone json ipad uisplitviewcontroller


【解决方案1】:

这里我为你提供完整的代码,这样做

#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

这是我的 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"]
  }]

这是我的输出

【讨论】:

  • 我喜欢您的解决方案,但我想保留我目前拥有的解决方案。虽然我能够创建一个数组,但我无法设置按钮标题:(有什么建议吗?
  • 调试代码并检查数组中的数据
  • 我已经解决了。由于某些奇怪的原因,我不得不在 for 循环中更改 i=1 而不是 i=0。
【解决方案2】:

fruitArray 数组是您方法中的局部变量。它永远不会存储在任何地方。无论你投入什么,它都不会产生任何影响。

顺便说一句。

使用 for (NSDictionary* dict in jsonArray) 之类的 for 循环,避免每次都进行缓慢的索引操作。

当它包含一个数组时,您假设关键水果包含一个字符串。那迟早会让你的程序崩溃。

不要使用 valueForKey,使用 objectForKey。最终你会用 valueForKey 得到非常令人惊讶的结果。

【讨论】:

    【解决方案3】:

    更新 JSON 后,您收到的不是 NSString 对象,而是 NSArray:

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

    所以你需要做这样的事情:

    NSArray *fruitsArray  = [[jsonArray objectAtIndex:i] valueForKey:@"fruit"];
    NSString *cFruit = [fruitsArray componentsJoinedByString:@","];
    

    【讨论】:

    • 我编辑了我的问题,我现在似乎无法设置按钮标题循环遍历数组
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-13
    相关资源
    最近更新 更多