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 に設定された辞書が nil にならないようにするにはどうすればよいですか?

__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 に答える
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 に答える
0

ブロックコードからweatherDictを宣言するときは、__blockキーワードを使用してください。

于 2016-01-11T02:03:21.143 に答える