1

非同期ブロックで関数を呼び出す共有操作を実行しようとしていますが、次の if ステートメントでは、ブロックで完了した値を取得して続行する必要があります。これは、詳細を強調する私のコードです。NSLock のことを聞いて使ってみましたが、うまくいきませんでした。何かロックをしているのかもしれません。ロックに詳しくありません。

-(void) shareOperation
{
__block NSString *resultText;
BOOL continueSharing;
 NSLock *conditionLock=[[NSLock alloc] init];
         dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
            [conditionLock lock];
        [self performSomeAsynchronousOperation completionBlock:^(NSError *tError, bool status)
         {
             dispatch_async(dispatch_get_main_queue(),
                            ^{

                                if (status)
                                {
                                    resultText = @"Operation completed. Would you like to continue?";

                                }
                                else
                                {
                                    resultText = @" Operation failed. Would you still like to continue?";
                                }
                                UIAlertView *result = [UIAlertView alertViewWithTitle:nil message:resultText cancelButtonTitle:@"Cancel" otherButtonTitles:[NSArray arrayWithObjects:@"OK",nil] onDismiss:^(int buttonIndex)
                                                       {
                                                           NSLog(@"selected button index: %d",buttonIndex);
                                                           if (buttonIndex == 0)
                                                           {
                                                               continueSharing=YES;
                                                               [conditionLock unlock];
                                                               NSLog(@"We are continuing sharing :)");
                                                           }
                                                       }onCancel:^{
                                                           continueSharing=NO;
                                                            [conditionLock unlock];
                                                           NSLog(@"cancelled");
                                                       }]; [result show];

                            });
         }];
        });
    }


    //should continue only after earlier if block finishes, ie after getting the continueSharing value

    if (continueSharing)
    {
        [self performSomeAnotherAsynchronousOperation];
    }

}
4

2 に答える 2

5

ロック (一部の共有リソースへの同時アクセスがないようにするためだけに設計されている) を使用する代わりに、セマフォ (あるスレッドが別のスレッドからのシグナルを待機できるように設計されているため、ここで必要です) を使用できます。

したがって、セマフォを作成する必要があります。

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

アラート ビューの完了ブロックは、そのセマフォを通知します。

dispatch_semaphore_signal(semaphore);

そして、そのシグナルを待ちたい場所(前performSomeAnotherAsynchronousOperation):

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

dispatch_semaphore_wait私はあなたのコードを少し調整しましたが、最も注目すべきは、バックグラウンド キューで実行されることを確認することで、メイン キューをブロックしないように変更したことです。がステートメントdispatch_semaphore_signal内にないことにも注意してください。ifこれにより、次の結果が得られました。

- (void)shareOperation
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __block BOOL continueSharing = NO;
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

        [self performSomeAsynchronousOperationWithCompletionBlock:^(NSError *tError, bool status){
            dispatch_async(dispatch_get_main_queue(),^{
                NSString *resultText;

                if (status)
                    resultText = @"Operation completed. Would you like to continue?";
                else
                    resultText = @"Operation failed. Would you still like to continue?";

                UIAlertView *alertView = [UIAlertView alertViewWithTitle:nil message:resultText cancelButtonTitle:@"Cancel" otherButtonTitles:@[@"OK"] onDismiss:^(int buttonIndex) {
                    NSLog(@"selected button index: %d",buttonIndex);
                    if (buttonIndex == 0) {
                        continueSharing = YES;
                        NSLog(@"We are continuing sharing :)");
                    }
                    dispatch_semaphore_signal(semaphore);
                } onCancel:^{
                    dispatch_semaphore_signal(semaphore);
                    NSLog(@"cancelled");
                }];

                [alertView show];
            });
        }];

        // should continue only after earlier if block finishes, ie after getting the continueSharing value

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        if (continueSharing)
            [self performSomeAnotherAsynchronousOperation];
    });
}

さらに良いことに、セマフォのようなブロック メカニズムを使用しないでください (もちろんメイン キューにはありません)。むしろ、プロセスの次のステップ自体を直接開始するアラート ビューの完了ブロックを使用する必要があります。これはあなたのシナリオでは実用的ではないとおっしゃっていることは理解していますが、一般的にこれらのシナリオを処理する正しい方法です。

于 2014-01-17T11:32:36.367 に答える