我正在尝试实现一个方法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
按要求运作?谢谢!
答案 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];
...
}