0

我正在尝试使用 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 中设置后不为零?

使用 __block 不起作用。

4

4 回答 4

1

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

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

使用 __block 不起作用。

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

正确的解决方案是在请求的完成块中设置标签——这就是完成块的用途

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

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

于 2016-01-11T18:54:17.547 回答
1

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

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

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

于 2016-01-11T18:42:49.157 回答
0

当您将 weatherDict 标出块代码时,请使用 __block 关键字。

于 2016-01-11T02:03:21.143 回答
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];

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

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

一旦你从服务器得到响应,你的块就会被调用,你应该把你的逻辑放在里面,就像现在一样。

于 2016-01-11T19:08:21.630 回答