iOS JSON 从 web 解析到 UITableView

Posted

技术标签:

【中文标题】iOS JSON 从 web 解析到 UITableView【英文标题】:iOS JSON parsing from web to a UITableView 【发布时间】:2013-10-26 17:12:21 【问题描述】:

我的代码遇到问题,但我不确定它为什么会这样。它只是给我一个错误,说 JSON 错误。 UITableView 永远不会被任何东西填满。我对 ios 不是很有经验,因此感谢您提供任何帮助。

//
//  ViewController.m
//  Westmount Procrastinator
//
//  Created by Saleem on 10/25/13.
//  Copyright (c) 2013 Saleem Al-Zanoon. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIWebView *webView;
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@end

@implementation ViewController
- (void)viewDidLoad 
    [super viewDidLoad];
    NSString *fullURL = @"********";
    NSURL *url2 = [NSURL URLWithString:fullURL];
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url2];
    [_webView loadRequest:requestObj];

    self.title = @"News";

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    NSURL *url = [NSURL URLWithString:@"****************"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection connectionWithRequest:request delegate:self];    //  NSString * urlString = [NSString stringWithFormat:@"http://salespharma.net/westmount/get_all_products.php"];
  //  NSURL * url = [NSURL URLWithString:urlString];
 //   NSData * data = [NSData dataWithContentsOfURL:url];
 //   NSError * error;
//    NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
//    NSLog(@"%@",json);

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    data = [[NSMutableData alloc] init];


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData

    [data appendData:theData];


- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    NSArray *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
    //news = [responseDict objectAtIndex:0];
    // [mainTableView reloadData];
    if ([responseDict isKindOfClass:[NSArray class]]) 
        news = responseDict;
        [mainTableView reloadData];
     else 
        // Looks like here is some part of the problem but I don't know why.
        NSLog(@"JSON Error.");

        UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not contact server!" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
        [errorView show];

    


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

    UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"The download could not complete - please make sure you're connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
    [errorView show];
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;


- (int)numberOfSectionsInTableView:(UITableView *)tableView

    return 1;


- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return [news count];


NSString *_getString(id obj)

    return [obj isKindOfClass:[NSString class]] ? obj : nil;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    if(cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Cell"];
    

    cell.textLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:@"Issue"]);
    cell.detailTextLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:@"Name"]);

    return cell;

   @end

JSON 在 Internet 上的样子:

    

   "Issues":[
      
         "Issue":"2",
         "Link":"google.com",
         "Name":"Ios Test"
      ,
      
         "Issue":"3",
         "Link":"Yahoo",
         "Name":"iOS test 2"
      
   ],
   "success":1

编辑:很抱歉我的问题不清楚,该应用程序不会崩溃,但无法将数据加载到日志中的数据库中:

2013-10-26 10:26:41.670 Westmount Procrastinator[2490:70b] JSON Error.
2013-10-26 10:26:41.671 Westmount Procrastinator[2490:70b] Server Data: 
"Issues":["Issue":"2","Link":"google.com","Name":"Ios Test"],"success":1

应用程序的目标是联系数据库下载一份报纸的问题列表,然后在列表视图中列出它们。然后允许用户单击这些问题并下载它们。

编辑我在 JSON 中添加了更多内容以帮助解释。

【问题讨论】:

您好,请提供更多详细信息,以便更好地回答您的问题。您应该提供以下详细信息:确切的错误消息/崩溃日志、应用程序崩溃的行、仅提供相关代码(不是您的所有代码),并请更详细地说明您正在尝试做什么以及您要做什么'真的在问。 *** 社区不是在这里为您调试程序,但我们在这里为您提供帮助 - 所以请更清楚地说明您的要求并提供更多详细信息。 您确定这是您应用中的 JSON 的实际外观吗?您从服务器返回的数据对象究竟是什么?您可以使用以下命令轻松打印出来:NSLog(@"Server Data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); 我已编辑问题添加更多信息,感谢您的快速回复。 【参考方案1】:

从您的示例 JSON 结构来看,它似乎不是 NSArray。它是 NSDictionary 。因此,在解析 JSON 数据时,将其保存在 NSDictionary 而不是 NSArray 中。此外,之后更改您的 IF 条件。

重要的是,如果您的 tableview 正在从 NSDictionaries 的 NSArray 中读取数据,那么我会说将此 NSDictionary 放入 NSArray 并将其传递给 table view。另外,从服务器端检查输出是什么,以防它们是您需要相应处理的多个字典。所以基本上你需要在这里引入更多的行,否则在所有情况下都要求数据提供者(服务器端)发送 NSArray。

NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
if ([responseDict isKindOfClass:[NSDictionary class]]) 
    NSArray *tableArray = [NSArray arrayWithArray:responseDict[@"Issues"]];

现在使用 tableArray 填充您的表格。

【讨论】:

感谢您的快速回复,在我的 PHP 代码中,实际显示 JSON 似乎是一个数组。 $Issues = array(); 但是您在问题中提出的示例 JSON 似乎不是 NSArray。你可能想检查一次。试试我分享的代码,你应该从你的 JSON 中得到一个 NSDictionary。 好吧,使用您提供的代码修复了一个问题但导致了另一个问题,日志现在很清楚,所以它不会抱怨,但表保持为空,Xcode 警告我:Incompatible pointer types assigning to 'NSArray *' from 'NSDictionary *' 所以我尝试更改类型从 NSarray 到 NSdictionary 的新闻。它给出了错误:No visible @interface for 'NSDictionary' declares the selector 'objectAtIndex:' 这行代码:cell.textLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:@"Issue"]); 我知道这一点,并在我的回答中警告您。因此,您的表视图需要一个 NSArray 而不是 NSDictionary。你需要按照我的回答逐字逐句。 再次,我一直在调查我正在使用与应用程序的 android 版本相同的数据库,它似乎是一个 NSArray。在 android 版本中,它循环遍历数组并获取问题......所以这让我相信它是一个数组。如果我尝试 NSDictionary 或 NSArray 任何进一步的建议/解决方案,我似乎无法让它发挥作用?【参考方案2】:

Issues 是一个字典数组,因此您应该在indexpath.row 处请求字典,然后使用objectForKey 从该字典中提取适当的值。

    NSDictionary *myDict = @@"Issues": @[@@"Issue": @"2",
                                            @"Link": @"google.com",
                                            @"Name": @"Ios Test",
                                          @@"Issue": @"3",
                                            @"Link": @"Yahoo",
                                            @"Name": @"iOS test 2"],
                             @"success": @"1";

    NSArray *issues = [myDict objectForKey:@"Issues"];

    [issues enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
        NSLog(@"Issue: %@ Link: %@ Name: %@", [obj objectForKey:@"Issue"], [obj objectForKey:@"Link"], [obj objectForKey:@"Name"]);
    ];

将返回:

2013-10-26 16:42:43.572 Jsontest[43803:303] Issue: 2 Link: google.com Name: Ios Test
2013-10-26 16:42:43.573 Jsontest[43803:303] Issue: 3 Link: Yahoo Name: iOS test 2

【讨论】:

以上是关于iOS JSON 从 web 解析到 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

从 Web API 解析 Json

从 Web 服务解析 JSON 数据时,没有返回数据

如何解析从 Web 服务响应收到的 JSON 响应

如何使用 iOS SDK 从 ASMX Web 服务中获取和解析 JSON?

使用 SimpleJSON 从 Web API 解析 Unity 中的 JSON 数据数组

如何在 iOS 7 中解析从 .NET Web 服务收到的 JSON 响应