0

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

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"; Name = Baseball; NumRatings = 106; Price = "$2.98"; Publisher = "Super Sportz, Inc."; Rating = "3.5"; }, {图标 = “Checkers.png”;名称 = Checkers;NumRatings = 87;价格 = 免费;出版商 =“Gameitoids, Inc.”;评级 = 4;})

问题是:为什么我无法访问块外的实例变量“数据”,甚至将其分配为 json 的结果?

4

4 回答 4

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

}];

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

一些链接:

于 2013-03-13T14:58:35.913 回答
0
  1. 时间(如上面的2个答案)
  2. 要写入块外的变量,您必须在变量声明之前使用 __block 指令。我不确定实例变量是否对此特别,但要确保您可以使用一些临时变量来存储结果,然后再将其最终分配给 ivar。
于 2013-03-13T15:05:42.683 回答
0
NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

美好的。你有什么问题?这是完成块。它在接收到所有数据时执行。在该时间点之前对数据的任何访问在最好的情况下最终将为零,在最坏的情况下将导致过时/错误/不可预测的数据。

于 2013-03-13T15:08:36.900 回答
0

这里发生的是你的日志

NSLog(@"Data only: %@", data);  //At this point, the "data" content is 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


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


    }];

获取所有数据的请求会执行完成块,所以你得到响应后想要做的任何事情都可以在完成块中完成

于 2013-03-13T14:53:49.593 回答