AFNetworking 2.0 解析的数据未显示在表格视图中

Posted

技术标签:

【中文标题】AFNetworking 2.0 解析的数据未显示在表格视图中【英文标题】:AFNetworking 2.0 parsed data not displaying in table view 【发布时间】:2014-04-06 18:29:55 【问题描述】:

我的问题:表格中没有显示数据。

下面是用于检索 json 对象数组并使用 AFNetworking 2.0 对其进行解析的代码。我有一个 UIViewController,我在其中放置了一个带有原型单元格的表格视图,该单元格具有重用标识符 EventCell。我想要的只是在每个单元格中显示标题和图像。我在运行时没有收到任何错误。

NSDictionary+events.h

#import <Foundation/Foundation.h>

@interface NSDictionary (events)

- (NSString *)eventImage;
- (NSString *)eventTitle;
- (NSDate *)eventDate;
- (NSNumber *)eventPrice;
- (NSNumber *)eventTicketsTotal;
@end

NSDictionary+events.m

#import "NSDictionary+events.h"

@implementation NSDictionary (events)



- (NSString *)eventImage

    return self[@"event_image"];



- (NSString *)eventTitle

    return self[@"event_title"];



- (NSDate *)eventDate

    //    NSString *dateStr = self[@"date"]; // date = "2013-01-15";
    return [NSDate date];


- (NSNumber *)eventPrice

    NSString *cc = self[@"event_price"];
    NSNumber *n = @([cc intValue]);
    return n;


- (NSNumber *)eventTicketsTotal
    NSString *cc = self[@"event_tickets_total"];
    NSNumber *n = @([cc intValue]);
    return n;


@end

NSDictionary+events_package.h

#import <Foundation/Foundation.h>

@interface NSDictionary (NSDictionary_events_package)

-(NSArray *)upcomingWeather;
@end

NSDictionary+events_package.m

#import "NSDictionary+events_package.h"

@implementation NSDictionary (NSDictionary_events_package)


- (NSArray *)upcomingWeather

    NSDictionary *dict = self[@"data"];
    return dict[@"events"];

@end

TDViewController.h

#import <UIKit/UIKit.h>
#import "NSDictionary+events.h"

@interface TDViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
@property(nonatomic, retain) UITableView *tableView;
@end

TDViewController.m

#import "TDViewController.h"

#import "UIImageView+AFNetworking.h"
#import "TDSecondViewController.h"
#import "NSDictionary+events_package.h"

static NSString * const BaseURLString = @"http://xx.zzz.yy.xx/test/";

@interface TDViewController ()

@property(strong) NSDictionary *events;

@end

@implementation TDViewController   

- (void)viewDidLoad

    [super viewDidLoad];

    // 1
    NSString *string = [NSString stringWithFormat:@"%@event_json.php?format=json", BaseURLString];
    NSLog(@"web service address: %@", string);

    NSURL *url = [NSURL URLWithString:string];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // 2
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFJSONResponseSerializer serializer];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 

        // 3
        self.events = (NSDictionary *)responseObject;
        NSLog(@"%@", responseObject);
        self.title = @"JSON Retrieved";

        [self.tableView reloadData];

     failure:^(AFHTTPRequestOperation *operation, NSError *error) 

        // 4
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Events"
                                                            message:[error localizedDescription]
                                                           delegate:nil
                                                  cancelButtonTitle:@"Ok"
                                                  otherButtonTitles:nil];
        [alertView show];
    ];

    // 5
    [operation start];




- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

    if([segue.identifier isEqualToString:@"WeatherDetailSegue"])
        UITableViewCell *cell = (UITableViewCell *)sender;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

        TDSecondViewController *wac = (TDSecondViewController *)segue.destinationViewController;

        NSDictionary *w;
        if (indexPath.section == 0) 
            
                w = [self.events upcomingWeather][indexPath.row];
                //NSLog( @"this is w: %@", w );
            
            wac.weatherDictionary = w;

        
    



#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    if(!self.events)
        return 0;

    NSArray *upcomingWeather = [self.events upcomingWeather];
    return [upcomingWeather count];
    NSLog( @"the count is %lu", (long)[upcomingWeather count]);


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

    static NSString *CellIdentifier = @"EventCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    NSDictionary *daysWeather = nil;


    NSArray *upcomingWeather = [self.events upcomingWeather];
    daysWeather = upcomingWeather[indexPath.row];
    NSLog( @"this is daysWeather: %@", daysWeather );
    cell.textLabel.text = [daysWeather eventTitle];
     NSLog(@"The content of arry is%@",daysWeather);

    NSURL *url = [NSURL URLWithString:daysWeather.eventImage];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    UIImage *placeholderImage = [UIImage imageNamed:@"placeholder"];

    __weak UITableViewCell *weakCell = cell;

    [cell.imageView setImageWithURLRequest:request
                          placeholderImage:placeholderImage
                                   success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) 

                                       weakCell.imageView.image = image;
                                       [weakCell setNeedsLayout];

                                    failure:nil];    
    return cell;


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    // Navigation logic may go here. Create and push another view controller.


@end

下面是我在模拟器上运行项目时得到的 nslog 输出(注意不是所有的 nslog 语句都在显示)。

2014-04-06 21:47:04.592 iCLUB[9198:60b] webservice address:     
http://xx.zzz.yy.xx/test/event_json.php?format=json
2014-04-06 21:47:04.685 iCLUB[9198:60b] 
data =     
    events =         (
                    
            "event_date" = "7-5-2014";
            "event_id" = 22;
            "event_image" = "http://xx.zzz.yy.xx/...";
            "event_price" = 150;
            "event_tickets_total" = 200;
            "event_title" = "New Event Title";
        ,
                    
            "event_date" = "3-2-2014";
            "event_id" = 23;
            "event_image" = "http://xx.zzz.yy.xx/...";
            "event_price" = 150;
            "event_tickets_total" = 200;
            "event_title" = "New Event Title 2";
        ,
                    
            "event_date" = "9-25-2014";
            "event_id" = 24;
            "event_image" = "http://xx.zzz.yy.xx/...";
            "event_price" = 150;
            "event_tickets_total" = 200;
            "event_title" = "New Event Title 33";
        
    );
;

我只是不知道问题出在哪里,应用程序在模拟器上构建并运行,但单元格看起来完全是空的。我将不胜感激任何帮助。谢谢,JT。

【问题讨论】:

你应该正确的模型类而不是 NSDictionary 上的类别。 可能的问题包括(a)您没有为表格视图连接IBOutlet(这会阻止reloadData做任何事情);或者 (b) 您没有将表视图的 delegatedataSource 设置为视图控制器(在这种情况下,对 reloadData 的任何调用都不会导致对您的 UITableViewDataSource 方法的调用)。我建议检查self.tableViewself.tableView.dataSource 是否不是nil AFNetworking 提供的仅仅是 NSURLSession。 @Joride 这并不完全正确。 AFHTTPSessionManager 提供请求和响应序列化功能以及简化的GETPOST 等方法,使构建复杂请求变得更加容易。诚然,AFNetworking 目前没有为 NSURLSession 提供基于 NSOperation 的模式,但 Mattt 报告说他正在努力解决这个问题。 【参考方案1】:

问题的可能来源包括:

无法连接表格视图的IBOutlet。如果tableView 属性没有正确连接,它将是nil,因此[self.tableView reloadData] 不会做任何事情(因为向nil 对象发送消息不会做任何事情)。

坦率地说,我不清楚这个 tableView 属性是如何设置的,因为它缺少在 Interface Builder 中连接控件时使用的典型 IBOutlet 限定,而且我也没有看到您以编程方式设置它。

未能将您的视图控制器指定为delegate,更重要的是,未能将表视图的dataSource 指定为。如果是这种情况,即使您成功调用了[self.tableView reloadData],也不会导致调用UITableViewDataSource 方法。

我建议检查self.tableViewself.tableView.dataSource 是否不是nil

【讨论】:

【参考方案2】:

解析json数据时,使用上面的代码

NSDictionary *dict = (NSDictionary *)responseObject;
    self.events = [dict objectForKey:@"data"];

【讨论】:

嗨,当我用上面的代码更改我的代码时,我仍然得到一组空白单元格。当我做 NSLog(@"self.eventst: %@", self.events);它显示我最初为 NSLog(@"%@", responseObject);显示在上面。【参考方案3】:

你记得给self.tableView设置delegate和dataSource吗?当您不继承 UITableViewController 时,它不会自动为您完成。

我认为您从 API 获取的 JSON 无效。 events 的数组应该用括号 [] 括起来,而不是括号。此外,JSON 不使用分号。请参阅 JSON spec。

【讨论】:

我的代码中没有分号。据我所知,JSON 是正确的。我上面显示的是 NSLog(@"%@", responseObject); 的输出。在 JSON 被消费之后。 我这样设置委托和数据源:self.tableView.delegate = self; self.tableView.dataSource = self;...没有变化。 @user3007683 是self.tableView 本身,而不是nil 其他 NSLog 语句是否正在执行?如果不是,TableView 没有调用tableView:cellForRowAtIndexPath: 还是有问题?也许您还没有初始化 self.tableView 本身(通过 IBOutlet 从 Storyboard/NIB 或 [[UITableView alloc] initWithFrame:]【参考方案4】:

    numberOfRowsInSection 中的这条 NSLog 语句永远不会被调用,因为该方法在语句之前返回!

        return [upcomingWeather count];
        NSLog( @"the count is %lu", (long)[upcomingWeather count]);
    

    似乎 cellForRowAtIndexPath 没有被调用,这可能是由于各种原因,包括未设置 UITableView 数据源和委托、numberOfRowsInSection 返回 0 或您的 TableView 为零。使用调试器可以让您查看正在发生哪些情况。

    查看 Apple 的 resources 进行调试。

【讨论】:

以上是关于AFNetworking 2.0 解析的数据未显示在表格视图中的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 2.0 JSON 解析

使用 AFNetworking 2.0 异常解析 JSON

AFNetworking 2.0:凭据未在前一次请求的 30 秒内发送到身份验证

AFNetworking 2.0:POST 返回成功响应但服务器未更新

尝试编译 AFNetworking 2.0 时架构 i386 的未定义符号

iOS - AFNetworking 的 JSON 解析