【问题标题】:Populate UITableView with JSON array使用 JSON 数组填充 UITableView
【发布时间】:2014-02-08 01:12:19
【问题描述】:

我在 Storyboard 中工作,但我想现在是时候面对代码了...

我的服务器上有一个 PHP 文件,它将我的 MySQL 数据库表的内容输出为 JSON 格式的数组:

{
"id":"2",
"name":"The King's Arms",
"city":"London",
"day":"Tuesday",
}

我最终将需要所有数据,但现在我只想将城市字段输出为 UITableView。我该怎么做呢?

【问题讨论】:

  • 你想知道如何从 JSON 对象中提取数据吗?
  • 是的,然后如何在 UITableView 中显示它们。
  • @Sebastian 现在为您编写指南。和我一起裸露。
  • 可爱,非常感谢

标签: ios objective-c json uitableview


【解决方案1】:

什么是 myCitysTable,Paven?这应该是 TableView 的名称吗?我正在努力弄清楚如何命名它,如果是这样的话......

【讨论】:

    【解决方案2】:

    我相信是在 2012/2013 年,Apple 报道了一段关于代码实践的精彩视频,其中强调的一个子主题是处理 JSON 对象并为它们创建数据对象的一种很好的智能方法。抱歉,我忘记了实际视频的名称,如果有人记得,请帮我编辑答案。

    Apple 所涵盖的是拥有一个存储每个 json 对象的数据对象。然后,我们将创建一个数组来存储这些对象,并在填充我们的 tableView 时适当地访问所需的字段。所以在你的情况下,你会做这样的事情。

    在您的项目导航器中添加一个 NSObject 类型的文件并添加以下代码:

    #import <Foundation/Foundation.h>
    @interface PlaceDataObject : NSObject
    
    -(id)initWithJSONData:(NSDictionary*)data;
    
    @property (assign) NSInteger placeId;
    @property (strong) NSString *placeName;
    @property (strong) NSString *placeCity;
    @property (strong) NSString *placeDay;
    
    @end
    

    并在您的 .m 文件中添加此代码

    #import "PlaceDataObject.h"
    @implementation PlaceDataObject
    @synthesize placeId;
    @synthesize placeName;
    @synthesize placeCity;
    @synthesize placeDay;
    
    -(id)initWithJSONData:(NSDictionary*)data{
        self = [super init];
        if(self){
            //NSLog(@"initWithJSONData method called");
            self.placeId = [[data objectForKey:@"id"] integerValue];
            self.placeName =  [data objectForKey:@"name"];
            self.placeCity = [data objectForKey:@"city"];
            self.placeDay = [data objectForKey:@"day"];
        }
        return self;
    }
    @end
    

    您现在拥有的是一个数据对象类,您可以在代码中任何需要的地方使用它,并为您显示的任何表获取适当的详细信息,无论是city 字段表还是city and name 表等. 通过这样做,您还可以避免在项目中到处都有 json 解码代码。当你的“钥匙”的名字改变时会发生什么?无需通过代码来纠正所有密钥,您只需转到 PlaceDataObject 类并更改适当的 key,您的应用程序将继续工作。

    Apple 很好地解释了这一点:

    “模型对象代表特殊的知识和专长。它们保存应用程序的数据并定义操作该数据的逻辑。设计良好的 MVC 应用程序将其所有重要数据封装在模型对象中......它们代表与特定问题领域相关的知识和专长,它们往往是可重用的。”

    为来自服务器的每个 json 条目使用自定义对象填充您的数组

    现在开始填充您制作的自定义数据对象的数组。现在遵循 MVC 方法,最好将所有处理数据的方法放在不同的类中,即 Model 类。这就是 Apple 建议将这些方法放在一个单独的模型类中进行所有处理的原因。

    但现在我们只是将以下代码添加到视图控制器中,仅用于演示目的。

    在视图控制器的 m 文件中创建一个方法来处理您的 JSON 数组。

    //make sure you have a global NSMutableArray *placesArray in your view controllers.h file.
    -(void)setupPlacesFromJSONArray:(NSData*)dataFromServerArray{
         NSError *error;
         NSMutableArray *placesArray = [[NSMutableArray alloc] init];
         NSArray *arrayFromServer = [NSJSONSerialization JSONObjectWithData:dataFromServerArray options:0 error:error];
    
         if(error){
             NSLog(@"error parsing the json data from server with error description - %@", [error localizedDescription]);
         } 
         else {
             placesArray = [[NSMutableArray alloc] init];
             for(NSDictionary *eachPlace in arrayFromServer)
             {
                 PlaceDataObject *place = [PlaceDataObject alloc] initWithJSONData:eachPlace];
                 [placesArray addObject:place];
             }
    
             //Now you have your placesArray filled up with all your data objects
         }
     }
    

    你会这样调用上面的方法:

    //This is not what your retrievedConnection method name looks like ;)
    // but you call the setupPlacesFromJSONArray method inside your connection success method
    -(void)connectionWasASuccess:(NSData *)data{
        [self setupPlacesFromJSONArray:data];
    }
    

    使用您的自定义数据对象填充您的 tableView

    至于在 TableView 中填充数据,您可以这样做:

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
         //We check against table to make sure we are displaying the right number of cells
         // for the appropriate table. This is so that things will work even if one day you 
         //decide that you want to have two tables instead of one.
         if(tableView == myCitysTable){
              return([placesArray count]);
         }
         return 0;
    }
    
    
     -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
         if(cell)
         {
              //set your configuration of your cell
         }
         //The beauty of this is that you have all your data in one object and grab WHATEVER you like
         //This way in the future you can add another field without doing much.
    
         if([placesArray count] == 0){
             cell.textLabel.text = @"no places to show";
         }
         else{
             PlacesDataObject *currentPlace = [placesArray objectAtIndex:indexPath.row];
             cell.textLabel.text = [currentPlace placeCity];
             // in the future you can grab whatever data you need like this
             //[currentPlace placeName], or [currentPlace placeDay];
         }    
         return(cell);
    }
    

    简短的免责声明:上面的代码尚未经过测试,但如果一切正常,或者我是否遗漏了任何字符,请告诉我。

    【讨论】:

    • 非常感谢,它看起来很棒。我现在坐下来实施它,并在可能的时候接受。
    • 现在检查代码,刷新页面,因为我添加了更多更改,例如数组验证等。
    • 一个问题 - 我在 Storyboard 中开发了我的界面,所以我没有 viewcontroller.m - 我在其他地方放置了该代码还是有办法找到该文件?跨度>
    • 您将代码放在哪里以从服务器检索数据?当然,您在某处有一些代码执行以下操作:grab data from server,大概与表格视图代码在同一页面中,对吧?这就是你要添加代码的地方——我写的地方add it to your viewController.m file
    • 啊,我有 php 文件在服务器上,但我还没有检索到它。
    【解决方案3】:

    如果来自您服务器的原始数据到达一个 NSData 对象,您可以使用 NSJSONSerialization 类为您解析它。

    即:

     NSError *error;
     NSMutableArray *cityArray = [[NSMutableArray alloc] init];
     NSArray *arrayFromServer = [NSJSONSerialization JSONObjectWithData:dataFromServer options:0 error:error];
     if(arrayFromServer)
     {
         NSLog(@"error parsing data - %@", [error localizedDescription]);
     } else {
        for(NSDictionary *eachEntry in arrayFromServer)
        {
             NSString *city = [eachEntry objectForKey:@"city"];
    
             [cityArray addObject: city];
        }
     }
    

    完成城市数组的填充后,您可以在表格视图的数据源方法中返回以下内容:

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1; // your table only has one section, right?
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
         if(section == 0)
         {
              return([cityArray count]);
         }
         NSLog(@"if we're at this place in the code, your numberOfSectionsInTableView is returning something other than 1");
         return 0;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         // are you using standard (default) cells or custom cells in your storyboard?
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
         if(cell)
         {
              cell.text = [cityArray objectAtIndex:indexPath.row];
         }
         return(cell);
    }
    

    【讨论】:

    • 我认为这不是填充数组的最佳方式。
    • 也许你是对的,@Pavan。你能做一个有更好方法的答案吗?我会投赞成票。
    • 在您的子类 UIViewController 中(这是您的 UI 所在的位置)。您需要将其声明为符合 并将您的 tableView 的数据源出口设置为指向它。
    • @MichaelDautermann douvle 检查您的代码中的dictionaryFromServer。 @sebastian 可能想知道那是什么
    • 谢谢@Pavan & Dinesh;我不是编译器,远不如你们。
    猜你喜欢
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多