如何在 UITableview 单元格中正确显示 JSON 数据?

Posted

技术标签:

【中文标题】如何在 UITableview 单元格中正确显示 JSON 数据?【英文标题】:How to display JSON data seperated correctly in UITableview cells? 【发布时间】:2016-07-16 23:50:15 【问题描述】:

我已经能够从本地 JSON 文件中获取数据以显示在 tableview 中

但它的显示如下:

........ 单元格 1........ ........

饼干

3 杯通用面粉

2 汤匙泡打粉

1/2 茶匙盐

........ 单元格 2....................... ........

12 个完整的晚餐卷或小三明治面包(我用的是全麦)

1 磅削薄的烤牛肉或火腿(或两者兼有!)

.................................................. .......

而且我需要它来显示分离到自己的单元格中的每种成分,如下所示:

........ 单元格 1........ ........

饼干

........ 单元格 2....................... ........

3 杯通用面粉

........ 单元格 3....................... ........

2 汤匙泡打粉

........ 单元格 4....................... ........

1/2 茶匙盐

........ 单元格 5........ ........

12 个完整的晚餐卷或小三明治面包(我用的是全麦)

....................... 单元格 6....................... ........

1 磅削薄的烤牛肉或火腿(或两者兼有!)

.................................................. …………

我需要什么代码才能正确显示数据?这是我当前的代码:

   /////////locations.json/////////////////////////////
    
      "locations": [

     "ingredients" : "Biscuits\n3 cups All-purpose Flour\n2 Tablespoons Baking Powder\n1/2 teaspoon Salt\nShortened for example” ,

     "ingredients" : "12 whole Dinner Rolls Or Small Sandwich Buns (I Used Whole Wheat)\n1 pound Thinly Shaved Roast Beef Or Ham (or Both!)\nShortened for example” ,  
    //many more records.  only included 2 for example                            
      ]
    
    /////////Location.h/////////////////////////////////////////
    #import <Foundation/Foundation.h>

    @interface Location : NSObject

    - (id)initWithJSONDictionary:(NSDictionary *)jsonDictionary;

    @property (readonly) NSString *ingredients;

    @end


    ////////Location.m////////////////////////////////////
    #import "Location.h"

    @implementation Location

    // Init the object with information from a dictionary
    - (id)initWithJSONDictionary:(NSDictionary *)jsonDictionary 
    if(self = [self init]) 
        // Assign all properties with keyed values from the dictionary

        _ingredients = [jsonDictionary objectForKey:@"ingredients"];
    
    return self;
    
    @end


    ////////JSONLoader.h////////////////////////////////////
    #import <Foundation/Foundation.h>

    @interface JSONLoader : NSObject

    // Return an array of Location objects from the json file at location given by url
    - (NSArray *)locationsFromJSONFile:(NSURL *)url;
    @end


    ////////JSONLoader.m////////////////////////////////////
    #import "JSONLoader.h"
    #import "Location.h"

    @implementation JSONLoader

    - (NSArray *)locationsFromJSONFile:(NSURL *)url 
    // Create a NSURLRequest with the given URL
    NSURLRequest *request = [NSURLRequest requestWithURL:url
                                             cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                                         timeoutInterval:30.0];

    // Get the data
    NSURLResponse *response;
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response  error:nil];

    // Now create a NSDictionary from the JSON data
    NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    // Create a new array to hold the locations
    NSMutableArray *locations = [[NSMutableArray alloc] init];

    // Get an array of dictionaries with the key "locations"
    NSArray *array = [jsonDictionary objectForKey:@"locations"];
    // Iterate through the array of dictionaries
    for(NSDictionary *dict in array) 
        // Create a new Location object for each one and initialize it with information in the dictionary
        Location *location = [[Location alloc] initWithJSONDictionary:dict];
        // Add the Location object to the array
        [locations addObject:location];
    

    // Return the array of Location objects
    return locations;

@end

////////TableViewController.h////////////////////////////////////
#import <UIKit/UIKit.h>
#import "Location.h"

@interface FilterViewController : UITableViewController

@property (weak, nonatomic) Location *location;

@end


////////TableViewController.m////////////////////////////////////
#import "FilterViewController.h"
#import "LocationsViewController.h"
#import "Location.h"
#import "JSONLoader.h"

@implementation FilterViewController 
    NSArray *_locations;   

- (void)viewDidLoad 
    [super viewDidLoad];

    // Create a new JSONLoader with a local file URL
    JSONLoader *jsonLoader = [[JSONLoader alloc] init];
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"locations" withExtension:@"json"];

    // Load the data on a background queue...
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
        _locations = [jsonLoader locationsFromJSONFile:url];
        // Now that we have the data, reload the table data on the main UI thread
        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

        );

// Just before showing the LocationDetailViewController, set the selected Location object
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    LocationsViewController *vc = segue.destinationViewController;
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    vc.location = [_locations objectAtIndex:indexPath.row];


#pragma mark - Table View Controller Methods

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FilterCell"];

    Location *location = [_locations objectAtIndex:indexPath.row];
    cell.textLabel.text = location.ingredients;
    cell.imageView.image = [UIImage imageNamed:@"ingredientsicon3232.png"];
    return cell;   

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return [_locations count];

@end

注意:我无法更改 JSON 数据格式,因为它来自外部来源,并且“成分”键比我在示例中发布的要多得多。

【问题讨论】:

我从你的代码中得到的是你使用了错误的数组来表示节数。如果您使用“位置”数组对象设置 cell.textlabel.text,那么也将其用于您的部分数量。然后将section中的行数设置为1。 @roozbehmo 感谢您分享您的建议。你能在代码中提供这个建议吗?我没有看到我的代码中的部分数量并试图理解。对此仍然很陌生,并正在努力学习。谢谢! 【参考方案1】:

编辑:

一些示例代码供您使用。

// JSONLoader.m 

- (NSArray *)locationsFromJSONFile:(NSURL *)url 
    // Existing code .......

    // Get an array of dictionaries with the key "locations"
    NSArray *array = [jsonDictionary objectForKey:@"locations"];
    // Iterate through the array of dictionaries
    for(NSDictionary *dict in array) 
        NSString *string = [dict objectForKey:@"ingredients"];
        NSArray *brokenIntoParts = [string componentsSeparatedByString:@"\n"];
        for (NSString *ingredient in brokenIntoParts) 
            [locations addObject:ingredient];
        
    

    // Return the array of Location objects
    return locations;


// FilterViewController.m

#pragma mark - Table View Controller Methods

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FilterCell"];

    cell.textLabel.text = [_locations objectAtIndex:indexPath.row];
    cell.imageView.image = [UIImage imageNamed:@"ingredientsicon3232.png"];
    return cell;   

原文:

您的代码看起来不错,实际上只是更改您的数据,


  "locations": [  "ingredients" : "Biscuits", 
                  "ingredients" : "3 cups All-purpose Flour",
                  "ingredients" : "Tablespoons Baking Powder"
.
.
.                                                               
]

这应该可以解决你的问题,基本上你想要key:value of "keyword":ingredient,如果没有请评论,祝你好运。

【讨论】:

@JingJingTao 我无法更改数据格式,因为它来自外部来源,并且“成分”键比我在示例中发布的要多得多。 :p,我想你可能会这么说,你可以尝试根据换行符分隔值。 对不起,我对此很陌生。你能提供一个代码示例来演示它是如何工作的吗? 不用担心,NSArray *brokenByLines = [yourString componentsSeparatedByString:@"\n"],这确实假设源中有换行符 我以前也尝试过这种方法,但我必须做错事,因为我得到了错误! 'NSArray' 没有可见的@interface 声明选择器'componentsSeperatedByString:'。也许我把那个代码放在错误的地方?我添加了 NSArray *brokenByLines = [_locations componentsSeparatedByString:@"\n"];在我的 tableviewcontroller 下: Location *location = [_locations objectAtIndex:indexPath.row];【参考方案2】:

此代码使用键值编码方法valueForKey从字典中提取ingredients,并将换行符分隔的字符串转换为数组。

NSDictionary *jsonDictionary =  @@"locations" : @[@ @"ingredients" : @"Biscuits\n3 cups All-purpose Flour\n2 Tablespoons Baking Powder\n1/2 teaspoon Salt\nShortened for example" ,
                                                   @ @"ingredients" : @"12 whole Dinner Rolls Or Small Sandwich Buns (I Used Whole Wheat)\n1 pound Thinly Shaved Roast Beef Or Ham (or Both!)\nShortened for example" ];


NSArray* locations = jsonDictionary[@"locations"];
NSMutableArray *ingredients = [NSMutableArray array];
NSArray *jsonIngredients = [locations valueForKey:@"ingredients"];
for (NSString *ingredient in jsonIngredients) 
    [ingredients addObjectsFromArray:[ingredient componentsSeparatedByString:@"\n"]];

NSLog(@"%@", ingredients);

结果ingredients可以直接作为数据源数组使用。

编辑:

你的模型类Location实际上与JSON数据格式不兼容

要尝试代码,您必须将结果 ingredients 分配给您的数据源数组 _locations

_locations = ingredients;

然后在cellForRowAtIndexPath 中替换行

Location *location = [_locations objectAtIndex:indexPath.row];
cell.textLabel.text = location.ingredients;

NSString *ingredient = _locations[indexPath.row];
cell.textLabel.text = ingredient;

PS:如果您还负责服务器端的 JSON,请考虑使用更方便的数据格式。

【讨论】:

过去几个小时,我一直在尝试将您的建议调整到我的代码中,但无法通过 countByEnumeratingWithState:objects:count 消息让应用停止崩溃。这是我根据您的回答尝试使用的代码: 位置 location = [_locations objectAtIndex:indexPath.row]; //NSArray 位置 = [_location valueForKey: @"locations"]; NSMutableArray *ingredients = [NSMutableArray 数组]; NSArray *jsonIngredients = [位置 valueForKey:@"ingredients"]; for (NSString *ingredient in jsonIngredients) [ingredients addObjectsFromArray:[ingredient componentsSeparatedByString:@"\n"]]; NSLog(@"%@", 成分); cell.textLabel.text = [成分 objectAtIndex:indexPath.row];我究竟做错了什么?有什么建议吗? 在过去的几个小时里,我以各种不同的方式尝试了您的建议。我可以在控制台中看到完整的成分数组,但无论我尝试什么,我都会遇到错误或崩溃。我会得到的崩溃错误是位置等于字符串,位置类不符合关键成分的键值,或者计数错误。通过您修改后的代码建议,我能够将数组结果一次返回到表格视图中,但表格视图显示的数据与原始问题中的数据相同(每个键/值组合在 1 个单元格中),代码如下 修改 JSONLoader 为:NSArray *array = [jsonDictionary objectForKey:@"locations"]; NSMutableArray *ingredients = [NSMutableArray 数组]; NSArray *jsonIngredients = [数组 valueForKey:@"ingredients"]; for (NSString *ingredient in jsonIngredients) [ingredients addObjectsFromArray:[ingredient componentsSeparatedByString:@"\n"]]; NSLog(@"%@", 成分); //和修改控制器: NSString *ingredient = _locations[indexPath.row]; cell.textLabel.text = [成分 valueForKey:@"成分"]; cell.textLabel.numberOfLines = 0; //为什么不分开呢?

以上是关于如何在 UITableview 单元格中正确显示 JSON 数据?的主要内容,如果未能解决你的问题,请参考以下文章

数据未显示在 UITableView 的自定义单元格中

如何在 Xcode swift 的 UITableview 单元格中显示当前股票价格?

如何使自定义单元格中的 UILabel 显示保存在 UITableView 中的更改

在 UITableView 单元格中定位 UIImageViews

在 uitableview 单元格中显示项目的评级

UITableView 单元格内容未正确显示