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

问题描述:

我试图在tableview中放入正确返回的JSON的结果。 问题是我只能访问返回信息的块内的数据,甚至将结果分配给实例变量。 我的代码如下:目标C - 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返回: 数据自:( { 图标=“Baseball.png “; Name = Baseball; NumRatings = 106; Price =”$ 2.98“; Publisher =”Super Sportz,Inc.“; Rating =”3.5“; }, { Icon =“Checkers.png”; 名称=跳棋; NumRatings = 87; 价格=免费; Publisher =“Gameitoids,Inc.”; 评分= 4; } )

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

完成响应可以在块外部访问data,但它被设置为nil。您可能正确设置了data,只是不在您想的那一刻。

当你执行最后的日志时,完成块还没有运行。请求是异步,这意味着完成块将在未来的某个时间点执行。这是了解使用块时的一个关键概念。

UPDATE

要procress数据一旦被retreived,你可以调用从完成块的目标:

[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

几个环节:

这里会发生什么事是你的日志

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

将获得data.You之前使用异步请求使用块是执行将发生在一个单独的线程不影响主线程执行

执行良好

,并在单独的线程中完成竣工块得到.Hence响应只加载执行到的数据在这一点上只有

为了更好的理解性

0123在这两个记录和完成块个
  • 认沽断点

你可以看到在日志中执行完毕块之前发生

编辑: 可以响应后做的操作在完成块分配给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] 


    }]; 

请求时获取所有数据将执行完成bl ock.So任何你想要做的事情后,可以在完成块

+0

我已经注意到了这一点,通过分析日志和毫秒的操作,但不明白为什么发生。感谢澄清。 但我该如何解决这个问题?我需要应用程序等待JSON的返回,然后将其分配给将由tableview使用的变量。 – Lano 2013-03-13 15:05:12

+0

是的,你可以在完成块中做到这一点 – 2013-03-13 15:09:10

+1

你可以通过同步请求数据来解决这个问题。你不希望这样做,因为那时你的应用程序将冻结在这一点上,直到最终收到数据。在某些情况下可能需要很长时间(直到ip超时)。 – 2013-03-13 15:10:26

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

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

好。你有什么问题?这是完成块。它在接收到所有数据时执行。在此时间点之前访问数据的任何情况最终都将以零为最终结果,或者在最差情况下以最长的数据结束/超时/不可预测的数据。