如何在块代码中保留数据?

时间:2016-01-11 01:59:18

标签: ios afnetworking-3

我正在尝试使用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无效。

4 个答案:

答案 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];

但我不认为这是事实。正如人们所说的那样,正确的做法是异步的。

只需将您的代码设置为阻止后的标签,或者根本不包含该标签。此代码的唯一目的是在未调用块时设置默认值。

只要您收到服务器的响应,您的块就会被调用,您应该将逻辑放在其中,就像现在一样。