我如何将数据保存在块代码之外?

how do i keep data once out of block code?

我正在尝试使用 AFNetworking 和 MJExtensions 解析 JSON link。 查看代码中的注释。

  - (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 中设置后不为零?

使用 __block 无效。

在块代码之外声明 weatherDict 时使用 __block 关键字。

块是异步的,这意味着 self.apparentTemperature.text = [NSString stringWithFormat:@"%f", weather.currently.apparentTemperature]; 可能会在设置了 weather 的块之前执行。

这就是为什么 self.apparentTemperature.text 总是 nil 在块之外的原因。

为了解决这个问题,只需调用一个函数,在该函数中将 UI 元素设置在块的末尾(但在块内),这样它将在块执行后调用。

//but if i set the label here, its always 0 (or nil for NSString)

那是因为该代码在网络请求完成之前运行,所以数据不存在。当您将块传递给异步方法(如网络调用)时,该块通常会在 在您发出调用的方法退出后 执行。

using __block didn't work.

不足为奇。 __block 确保如此标记的变量在块内使用本身而不是在块的上下文中复制,但它不会使数据返回得更快。

此处正确的解决方案是在请求的完成块中设置标签 - 完成块就是这样 for.

how do i keep data once out of block code?

不要尝试 -- 没有理由不在块内设置变量。

你可以只使用信号量:

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

但我认为情况并非如此。正如人们所说,正确的做法是异步。

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

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