20758


iOSでネットワークから取得した値を返り値として利用する場合、非同期処理の完了(サーバからのデータ取得)を待ってその値を使う必要があり、私はそのためにセマフォを使って処理の完了を待っていますがうまくいかないことがあったので質問します。

下記メソッドでセマフォを使った所、アプリが止まってしまったので、その対策方法を知りたいです。

デバッガでアプリが止まった部分を確認してみると、AFNetworkingのsessionManagerのGETメソッドを行った直後で止まっています、サーバの処理は完了しているので、ブロックの処理の所でアプリが停止してしまっている様です。

[code]

    - (BOOL)checkUpdate {
    __block BOOL needUpdate = NO;
    
    // セマフォを使うことで非同期処理を同期処理にする
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [[APIClient sharedClient] checkUpdateWithCompletion:^(NSDictionary *result, NSError *error) {
            if (error) {
                NSLog(@"失敗: %@", error);
            } else {
                // サーバの結果を取得
                needUpdate = [result[@"result"] boolValue];
            }
            dispatch_semaphore_signal(semaphore);
    }];
    // ブロックの完了を待つ
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    return needUpdate;
    
    }
    
[/code]

もし原因わかる方いましたらご教授お願いします。


CC BY-SA 3.0
2016-01-08T06:48:03.067
20743
2016-01-08T15:10:27.840
12232
question
ios
iOSでの非同期処理の同期化


AFNetworkingのsessionManagerのGET処理は  
Block構文内の処理を **メインスレッド** での処理として流しているため、  
`dispatch_semaphore_signal(semaphore);`が実行されません。  
上記ソースコードで言うところの`if (error) { ...`以降が実行されていません。

これは、  
`dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);`  
を実行することで、スレッド上の処理を停止しているためです。

よって、処理の終了を確認できないため、  
`dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);`  
より後ろの処理を実行することはできません。

解決方法ですが、  
セマフォは使わずに、 **デリゲート** もしくは **Block構文** を使ってみてはいかがでしょうか？

少しでも参考になれば幸いです。


CC BY-SA 3.0
2016-01-08T15:10:27.840
20758
2016-01-08T15:10:27.840
8968
20743
answer