0

最初
はこれを持っています

ZTCAPIClient *api = [ZTCAPIClient sharedClient];
__block BOOL sessionSuccess = NO;
//Get session
[api getPath:@"api-getsessionid.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
    NSMutableDictionary *dict = [self dealWithZTStrangeJSON:JSON];
    if ([dict count]) {
        NSLog(..something..);
        sessionSuccess = YES;
        NSLog(@"inside:%u",sessionSuccess);
    } else {
        NSLog(@"ERROR: Get no session!");
        sessionSuccess = NO;
    }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"ERROR: %@",error);
    sessionSuccess = NO;
}];
[api.operationQueue waitUntilAllOperationsAreFinished];
NSLog(@"outside:%u",sessionSuccess);

しかし、私は得るでしょう:

outside:0
inside:1

私はそれが非同期の理由であることを知っています。それで私はインターネットで検索しました、そして私はこれを見つけました:複数の操作が実行されるまで待つ-完了ブロックを含む(AFNetworking)

だから私はそれを試してみます:

ZTCAPIClient *api = [ZTCAPIClient sharedClient];
__block BOOL sessionSuccess = NO;
dispatch_group_t group = dispatch_group_create();
//Get session
dispatch_group_enter(group);
[api getPath:@"api-getsessionid.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
    NSMutableDictionary *dict = [self dealWithZTStrangeJSON:JSON];
    if ([dict count]) {
        NSLog(..something..);
        sessionSuccess = YES;
        NSLog(@"inside:%u",sessionSuccess);
    } else {
        NSLog(@"ERROR: Get no session!");
        sessionSuccess = NO;
    }
    dispatch_group_leave(group);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"ERROR: %@",error);
    sessionSuccess = NO;
    dispatch_group_leave(group);
}];
//[api.operationQueue waitUntilAllOperationsAreFinished];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
DLog(@"outside:%u",sessionSuccess);

それから私は何も得られません...何も出力されません。

どこが間違っているのですか?

4

1 に答える 1

3

プログラムがへの呼び出しを超えて移動することはないため、おそらく出力は得られませんdispatch_group_wait。もしそうなら、あなたは「外部」ログステートメントを見るでしょう。

が戻ってこない場合dispatch_group_waitは、グループ内に何かが残っている必要があります。サンプルコードでは、を使用してグループに1つ追加し、をdispatch_group_enter使用してapi呼び出しの成功ハンドラーまたは失敗ハンドラーのいずれかでそれを削除しますdispatch_group_leave。これはdispatch_group_leave、何らかの理由で呼び出されていないことを意味します。

私の疑いは、ブロックが呼び出されない理由は、外部コードが実行されているのと同じディスパッチキューで非同期に呼び出されるためです。この場合、それらは戻るまで実行できず、ブロックが実行されるまでdispatch_group_wait戻ることができません。dispatch_group_waitこれはデッドロックと呼ばれます。(編集:あるいは、成功または失敗のブロックを呼び出すプログラムの一部がデッドロックにつながる部分である可能性があります。いずれにせよ、結果として、ブロックはdispatch_group_wait戻らないため呼び出せません。)

もう1つの可能性は、メソッド-dealWithZTStrangeJSON:が何らかの理由で返されないことです。この場合、成功ブロックが呼び出されます(最初の行にブレークポイントを設定して確認できます)が、に到達することはありませんdispatch_group_leave

いずれの場合も、操作が終了するのを待つのではなく、別の方法で問題を解決することを検討することをお勧めします。おそらく、dispatch_group_wait代わりに成功ハンドラー内に戻った後に実行することを計画していたことを実行できます(または、成功または失敗ハンドラーが、現在実行していることを実行するメソッドを呼び出すことができるという別の考え方もあります)dispatch_group_wait—どちらの方法でも機能しますが、すべてのコードをブロックに入れるのではなく、メソッドを呼び出すことでコードを整理する方が簡単な場合があります。これは、成功の合間にコードを共有したい場合に特に便利です。および障害ブロック)。

于 2013-03-25T02:11:05.483 に答える