显示提醒并等待按下按钮

时间:2016-03-09 13:10:33

标签: objective-c multithreading grand-central-dispatch uialertcontroller nsrunloop

我正在尝试实现一个方法alertAndWait,该方法在从主线程“直接”调用时应该有效,并且在调度时如下:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    dispatch_sync(dispatch_get_main_queue(), ^{
        call alertAndWait
...

当调用alertAndWait时,将打开一个警报窗口,当前线程正在(非忙)等待。按下确定按钮后,警报消失,当前线程继续。

我的“解决方案”无法正常运行。我知道原因:并行dispatch_sync导致死锁 - 阻塞......但我不知道如何防止它......

- (void)viewDidAppear:(BOOL)animated {

    // called from main thread
    NSLog(@"Step 1");
    [self alertAndWait];
    NSLog(@"Step 4");

    // called from background thread
    NSLog(@"Step 1");
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        dispatch_sync(dispatch_get_main_queue(), ^{
            [self alertAndWait];
             NSLog(@"Step 4");
        });
    });
}

- (void)alertAndWait {
        NSLog(@"Step 2");
        __block BOOL ok = NO;
        UIAlertController* myAlert = [UIAlertController alertControllerWithTitle:@"Alert"
                                                                         message:@"Please press OK to continue"
                                                                  preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
                                                               handler:^(UIAlertAction * action) {
                                                                   ok=YES;
                                                               }];
        [myAlert addAction:continueAction];
        [self presentViewController:myAlert animated:NO completion:nil];
        while(!ok) {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        };
        NSLog(@"Step 3");
}

预期输出是这样的:

AlertNWait[9879:164395] Step 1
AlertNWait[9879:164395] Step 2
AlertNWait[9879:164395] Step 3
AlertNWait[9879:164395] Step 4
AlertNWait[9879:164395] Step 1
AlertNWait[9879:164395] Step 2
AlertNWait[9879:164395] Step 3
AlertNWait[9879:164395] Step 4

在步骤2之后,警报打开,当用户按下OK按钮时,步骤3开始。

但是现在,当按下OK(第二次)时,日志在“步骤2”之后结束:

AlertNWait[9879:164395] Step 1
AlertNWait[9879:164395] Step 2
AlertNWait[9879:164395] Step 3
AlertNWait[9879:164395] Step 4
AlertNWait[9879:164395] Step 1
AlertNWait[9879:164395] Step 2

为方便起见,我已将Xcode项目上传到github

有没有办法让alertAndWait按要求运作?谢谢!

1 个答案:

答案 0 :(得分:0)

在这种情况下你不能等待,但你可以将完成块传递给alertAndWait,以便在警报解除后执行。

- (void)viewDidAppear:(BOOL)animated {
    // called from main thread
    NSLog(@"Step 1");
    [self alertAndWait:^() {
        // do whatever you want here
    }];
    NSLog(@"Step 4");
}

- (void)alertAndWait:(void (^)())block {
    UIAlertController* myAlert = ...
    ...
    [self presentViewController:myAlert animated:NO completion:block];
    ...
}