UIAlertController不会立即显示

时间:2016-05-27 17:04:44

标签: ios9 uialertview uialertcontroller

Xcode版本:7.2.1,iOS版本:9.1 +

我正在尝试在iPad上显示一条UIAlertController警告消息,显示"正在加载...请等待"没有任何按钮的消息。我在开始长操作之前呈现UIAlertController,然后在长操作之后,我解除了UIAlertController。 然而,正在发生的事情是UIAlertController不会立即显示。它只会在较长的操作完成后短暂闪烁,然后被解除。

以下是一般代码结构:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Loading" message:@"Please wait...\n\n\n" preferredStyle:UIAlertControllerStyleAlert];
    [self presentViewController:alert animated:YES completion:nil];

    /// Perform long operation here...
    /// (Basically, a message is being sent to a server, a long operation happens on 
    /// the server, and then the server returns a response to the iPad client.)

    [alert dismissViewControllerAnimated:YES completion:nil];
}

我尝试了很多替代方案,例如使用dispatch_async,以便在长时间操作时同时显示警报消息:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Loading Dataset" message:@"Please wait...\n\n\n" preferredStyle:UIAlertControllerStyleAlert];
    [self presentViewController:alert animated:YES completion:nil];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{          

        /// Perform long operation here...

        dispatch_async(dispatch_get_main_queue(), ^{

            [alert dismissViewControllerAnimated:YES completion:nil];
        });
    });
}

我已经尝试过使用UIAlertView(我知道在iOS 8中已经弃用),无论是单独使用还是使用调度,但这都不起作用。

我尝试在performSelector消息中包装长操作代码,但无济于事。

过去,使用带有dispatch_queue的UIAlertView可以无缝地处理这种情况。

感谢任何帮助。

修改

有一点值得注意:在dispatch_async代码中,如果我在调用长操作代码之前添加一个usleep(250000),大约80%的时间,UIAlertController警报消息将在正确的时间显示:BEFORE漫长的行动开始了。但是,这不是100%的时间,也不是可持续的解决方案。用较小的号码拨打usleep是行不通的。

请注意,对于DISPATCH_QUEUE_PRIORITY_DEFAULT选项,我也尝试过: DISPATCH_QUEUE_PRIORITY_HIGH,DISPATCH_QUEUE_PRIORITY_LOW和DISPATCH_QUEUE_PRIORITY_BACKGROUND

而且,我也尝试了以下内容:

dispatch_queue_t myQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);

dispatch_async(myQueue, ^{
    /// Perform long operation here...
    dispatch_async(dispatch_get_main_queue(), ^{
        [alert dismissViewControllerAnimated:YES completion:nil];
    });
});

3 个答案:

答案 0 :(得分:1)

最终工作的是调度代码和CFRunLoopWakeUp调用的组合(由@Bhavuk Jain建议)。我还要做的是将最初在调度块之后的代码(我没有在原始帖子中显示)移动到调度块中。所以,到目前为止,以下工作正在进行:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // Initialize and present the alert view controller.
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Loading Dataset" message:@"Please wait...\n\n\n" preferredStyle:UIAlertControllerStyleAlert];
    [self presentViewController:alert animated:YES completion:nil];

    // Force wake up the run loop.
    CFRunLoopWakeUp(CFRunLoopGetCurrent());

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{          

        /// Perform long operation here...

        dispatch_async(dispatch_get_main_queue(), ^{

            [alert dismissViewControllerAnimated:YES completion:nil];

            /// Execute rest of code INDSIDE the dispatch code block INSTEAD of after it...
        });
    });
}

答案 1 :(得分:0)

当您出示警报控制器时,请尝试将CFRunLoopWakeUp(CFRunLoopGetCurrent())置于下方。

答案 2 :(得分:0)

在我标记为答案的原始帖子(5月31日)中,有一些情况下AlertViewController消息只会挂起,因为不会调用dismissViewController方法。 (也许在各种线程中有一些竞争条件......我不确定。)所以我最终发现可靠地运行并且看起来更清洁的解决方案是使用AlertViewController的完成块和dispatch_after调用的组合。

来自iOS reference的完成调用的更多信息:“在显示的视图控制器上调用viewDidAppear:方法后,将调用完成处理程序。”

This post有帮助。)

gcc alleg5test.c -o alleg5test -L/usr/local/lib -lallegro -lallegro_main
./alleg5test