我正在尝试使用AFNetworking和MJExtensions解析JSON链接。 请参阅代码中的注释。
- (void)viewDidLoad {
[super viewDidLoad];
NSString *apiURL = @"https://api.forecast.io/forecast/APIKEY/Lat,Long";
NSURL *URL = [NSURL URLWithString:apiURL];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
weatherDict = (NSDictionary *)responseObject;
weather = [WeatherClasses mj_objectWithKeyValues:weatherDict];
//----------------------
//when i set the label.text here, the label shows whatever the JSON value is
self.apparentTemperature.text = [NSString stringWithFormat:@"%f", weather.currently.apparentTemperature];
NSLog(@"Temp: %f", weather.currently.apparentTemperature);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
//--------------------------
//but if i set the label here, its always 0 (or nil for NSString)
self.apparentTemperature.text = [NSString stringWithFormat:@"%f", weather.currently.apparentTemperature];
}
在成功块中,我的词典有数据,但是当我离开成功块时,字典是零。我怎样才能使字典在AFHTTPSessionManager中设置后不是nil?
使用__block无效。
答案 0 :(得分:1)
块是异步的,这意味着self.apparentTemperature.text = [NSString stringWithFormat:@"%f", weather.currently.apparentTemperature];
可能会在块之前执行,其中weather
已设置。
这就是self.apparentTemperature.text
始终在nil
之外的原因。
要解决这个问题,只需调用一个函数,在块的末尾设置UI元素(但在块内),这样就会在块执行后调用它。
答案 1 :(得分:1)
//but if i set the label here, its always 0 (or nil for NSString)
那是因为该代码在网络请求完成之前运行,因此数据不存在。当您将块传递给网络调用之类的异步方法时,该块通常会在调用已退出的方法之后执行。
使用__block无法正常工作。
不足为奇。 __block
确保如此标记的变量本身在块内使用,而不是在块的上下文中重复,但它不会使数据更快地恢复。
这里正确的解决方案是在请求的完成块中设置标签 - 这就是完成块 的那种东西。
如何将数据保存在块代码之外?
不要尝试 - 没有理由不在块内设置变量。
答案 2 :(得分:0)
当您使用区块代码解析weatherDict时,请使用__block关键字。
答案 3 :(得分:0)
你可以使用信号量:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
...
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
self.apparentTemperature.text = [NSString stringWithFormat:@"%f", weather.currently.apparentTemperature];
但我不认为这是事实。正如人们所说的那样,正确的做法是异步的。
只需将您的代码设置为阻止后的标签,或者根本不包含该标签。此代码的唯一目的是在未调用块时设置默认值。
只要您收到服务器的响应,您的块就会被调用,您应该将逻辑放在其中,就像现在一样。