目标C - 正确返回后JSON数据不可用

时间:2013-03-13 14:50:37

标签: objective-c json

我正在尝试在tableview中输入正确返回的JSON的结果。 问题是我只能访问返回信息的块内的数据,甚至可以将结果分配给实例变量。 我的代码如下:

NSURL *url = [NSURL URLWithString:@"http://www.my_url.com.br/app/?type=list&info=15,16&lat=some_data&long=some_data"];

ASIHTTPRequest *_request = [ASIHTTPRequest requestWithURL:url];
ASIHTTPRequest *request = _request;

request.requestMethod = @"POST";
[request addRequestHeader:@"Content-Type" value:@"application/json"];

[request setDelegate:self];
[request setCompletionBlock:^{
    NSString *responseString = [request responseString];

    NSLog(@"Response: %@", responseString);
    NSDictionary *root = [NSJSONSerialization JSONObjectWithData:request.responseData options:0 error:nil];
    self.data = [root objectForKey:@"listing"];

    NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

}];
[request setFailedBlock:^{
    NSError *error = [request error];
    NSLog(@"Error: %@", error.localizedDescription);
}];

[request startAsynchronous];

NSLog(@"Data only: %@", data);  //At this point, the "data" content is nil

这是我的“ListDataController.h”文件定义:

@interface ListDataController : UITableViewController{
ApplicationCell *tmpCell;
    NSArray *data;
    UILabel *status ;       
UINib *cellNib;
}

@property (nonatomic, retain) IBOutlet ApplicationCell *tmpCell;
@property (nonatomic, retain) NSArray *data;

JSON返回:     数据自我:(         {         Icon =“Baseball.png”;         名字=棒球;         NumRatings = 106;         价格=“2.98美元”;         出版商=“Super Sportz,Inc。”;         评级=“3.5”;     },         {         Icon =“Checkers.png”;         名字= Checkers;         NumRatings = 87;         价格=免费;         Publisher =“Gameitoids,Inc。”;         评级= 4;     } )

问题是:为什么我不能访问块外的实例变量“data”,甚至为它分配json的结果?

4 个答案:

答案 0 :(得分:1)

您可以访问该区域外的data,但会将其设置为nil。您可能正确设置data,而不是在您想到的那一刻。

当您执行最终日志时,完成块尚未运行。请求是异步,这意味着完成块将在将来的某个时刻执行。这是使用块时理解的关键概念。

<强>更新

要在检索数据后对其进行处理,您可以从完成块中调用所需的数据:

[request setCompletionBlock:^{
    NSString *responseString = [request responseString];

    NSLog(@"Response: %@", responseString);
    NSDictionary *root = [NSJSONSerialization JSONObjectWithData:request.responseData options:0 error:nil];
    self.data = [root objectForKey:@"listing"];

NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

    [self handleData:self.data];  // you would have to define this method your self

}];

要考虑的一件事是,如果要基于self.data更新UI,则需要确保在主线程上执行handleData

一些链接:

答案 1 :(得分:0)

这里发生的是你的日志

NSLog(@"Data only: %@", data);  //At this point, the "data" content is nil

将在获取数据之前执行。您正在使用异步请求使用块,即执行将在单独的线程上发生而不影响主线程执行

并且在单独的线程完成时,完成块被执行.Hence响应仅在此时加载到数据中

为了更好的理解

  • 在日志和完成块中放置断点

您可以看到日志上的执行发生在完成块之前

编辑: 您可以在分配给data

的响应后执行完成块中的操作
   [request setCompletionBlock:^{
        NSString *responseString = [request responseString];

        NSLog(@"Response: %@", responseString);
        NSDictionary *root = [NSJSONSerialization JSONObjectWithData:request.responseData options:0 error:nil];
        self.data = [root objectForKey:@"listing"];

        NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly


        //DO here WHATEVER you want to do after getting response
    //eg:
        [table reloadData]


    }];

获取所有数据时的请求将执行完成块。所以在获得响应后您想要做的任何事情都可以在完成块中完成

答案 2 :(得分:0)

  1. 时间安排(如上面的2个答案)
  2. 要写入生活在块外的变量,必须在变量声明之前使用__block指令。我不确定实例变量是否特殊,但是为了确保你可以使用一些临时变量来存储结果,然后再将它最终分配给ivar。

答案 3 :(得分:0)

NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

精细。你有什么问题?这是完成块。它在收到所有数据时执行。在该最佳情况下,在该时间点之前对数据的任何访问将最终为零,或者在最坏的情况下最终为out / wron /不可预测的数据。