プログラム初心者です。  
viewDidLoadにてgetFlagメソッドを呼び、非同期でサーバーから情報を取得し、その値をviewWillAppearで使用したいのですが、下記のようなコードですと「isFlag」に値がセットされる  
タイミングが遅く、viewWillAppearが実行されるタイミングに間に合いません。  
このような場合どのようにすれば良いでしょうか。

```

    @interface hogeViewController(){
        BOOL isFlag; 
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self getFlag];
    }
    
    -(void) viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
    
        if(isFlag){
            ...
        }else{
            ...
        }
    }
    
    -(void) getFlag{
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
        NSString *serverInfo_ = nil;
        serverInfo_ = [NSString stringWithFormat:@"https://%@", WebServerInfo];
        NSString *mediaApi = [serverInfo_ stringByAppendingFormat:@"/api/hoge/"];
    
        NSURL *url_ = [NSURL URLWithString:mediaApi];
        [request setHTTPMethod:@"GET"];
    
        [NSURLConnection sendAsynchronousRequest:request
                                        queue:[NSOperationQueue mainQueue]
                            completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                                if(data){
                                    isFlag = true;
                                }
                            }];
    }
    
```
CC BY-SA 4.0
2018-05-24T04:03:51.027
44206
2020-08-07T05:01:50.173
28641
question
ios xcode objective-c
iosでのhttpリクエスト（GET）のタイミングについて
こんにちは！

非同期、つまり、いつ返ってくるかわからないデータを `viewWillAppear`
で利用する、というアプローチが間違っていると思います。御存知の通り、`viewWillAppear`
はviewが表示される直前に呼ばれるメソッドですので、getFlag の処理が終わるのは待ってくれません。

どうしても`viewWillAppear` で利用したいのであれば、非同期ではなく、同期でやるしかないと思いますよ！
CC BY-SA 4.0
2018-05-24T04:30:36.377
44208
2018-05-24T04:30:36.377
369
44206
answer
はじめまして。私も@小川
航佑さんと同じく、`hogeView`を表示する前にデーターの取得を完了しているのが望ましいと思うのですが、`hogeView`がアプリケーションが起動した最初の`view`である場合など、ままならない場合もありますよね。  
そこで、今のソースを極力変えずにサーバーからの値で挙動を変える方法を２つ程考えて見ました。

  * 一つ目は同期でデーターを取得する方法。

これは、`- (void) getFlag`を修正して、

```

    - (void) getFlag
    {
        NSString *serverInfo_ = nil;
        serverInfo_ = [NSString stringWithFormat:@"https://%@", WebServerInfo];
        NSString *mediaApi = [serverInfo_ stringByAppendingFormat:@"/api/hoge/"];
    
        NSURL *url_ = [NSURL URLWithString:mediaApi];
        NSData *data = [NSData dataWithContentsOfURL:url];
    
        if (data)
        {
            // dataが空でないとき
        }
        else
        {
            // dataが空の時
        }// end if data
    }// end - (void) getFlag
    
```

  * もう一つは同期処理の完了を待つ方法

こちらは一つ目の方法でも待ち時間は同じなんだから非同期転送に慣れておこうという考え方です。  
当然、前者より面倒くさくなります。

まず、メンバー変数に転送が終わったかのフラグを用意し、初期化します。

```

    @interface hogeViewController(){
        BOOL isFlag; 
        BOOL getDataDone;  // 転送完了を待つためのフラグ
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        getDataDone = NO;　// データ取得前に転送完了フラグを初期化
        [self getFlag];
    }
    
```

次に、非同期通信のコンプリーションハンドラーでデータの取得が完了時にこのフラグを立てる様にします

```

    [NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue mainQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                            if(data){
                                isFlag = true;
                            }
                            getDataDone = YES;  // コンプリーションハンドラーの最後で転送完了フラグを立てる
                        }];
    
```

そして、`viewWillAppear`の中でコンプリーションハンドラーが終わるまで待ちます

```

    -(void) viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
    
            // 転送完了を待つ処理
        while(!getDataDone)
        {
            [NSThread sleepTimeInterval:0.1];
        }//end while getDataDone become true
             // getDataDoneがYESになったら以降の行に進む
        if(isFlag){
            ...
        }else{
            ...
        }
    }
    
```

申し訳ありませんが動作確認をしていないので、必要に応じて 変数に `__block`宣言を追加するなどしてください
CC BY-SA 4.0
2018-05-24T07:26:58.447
44214
2018-05-24T07:57:36.790
2018-05-24T07:57:36.790
14745
14745
44206
answer