UIAlertController 没有立即显示

Posted

技术标签:

【中文标题】UIAlertController 没有立即显示【英文标题】:UIAlertController not displaying immediately 【发布时间】:2019-06-26 00:53:33 【问题描述】:

我是 Swift 编程新手,但找不到我的问题的答案,即...

当我展示一个带有 UIAlertAction 处理程序的简单 UIAlertController 时,我希望在用户响应之前显示警报,然后执行处理程序,然后继续执行剩余的代码。

出乎意料的是,它似乎在显示警报和执行处理程序之前完成了代码块。

我搜索了 ***,并重新阅读了有关 UIAlertController 和 UIAlertAction 的 Apple 开发人员文档,但我无法弄清楚为什么代码在用户响应之前不会暂停。

我已尝试将 UIAlertController 代码放入它自己的函数中,但警报似乎仍然显示不按顺序显示。我在想可能需要延迟才能让警报在下一行代码执行之前绘制(?)。

@IBAction func buttonTapped(_ sender: Any) 

    let alert = UIAlertController(title: "Ouch", message: "You didn't have to press me so hard!", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Sorry", style: .default, handler:  _ in
        self.handleAlert()
    ))
    self.present(alert, animated: true, completion: nil)

    print("Should be printed last!")


func handleAlert() 
    print("UIAlertAction handler printed me")

在上面的代码中,我希望调试控制台会显示:

UIAlertAction 处理程序打印了我 应该最后打印!

但它却显示:

Should be printed last!
UIAlertAction handler printed me

【问题讨论】:

这是正确的行为。显示警报不会阻塞主线程,因此buttonTapped 完成。为什么要阻止它? 感谢您的及时回复 vacawama。我正在开发一个简单的测验应用程序(用于练习)。用户单击 UIButton 来选择答案,在测验结束时,我希望显示一个提醒说“做得好,你想再试一次吗?”处理程序将在开始显示 Q1 之前重置分数等。但它会在显示或处理警报之前显示 Q1。 handleAlert()例程调用重置分数并显示Q1的代码。 将您希望在用户响应后发生的所有事情都放在警报操作处理程序中。 【参考方案1】:

除了添加单独的功能,您可以像这样将它放在警报操作本身中吗...

let alert = UIAlertController(title: "Ouch", message: "You didn't have to press me so hard!", preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "Sorry", style: .default, handler:  action in

// code for action goes here

))

self.present(alert, animated: true)

【讨论】:

【参考方案2】:

UIAlertController 被设计为异步运行(这就是为什么它让你在执行操作时传递一段代码来执行而不是给出返回值)

因此,要修复您的代码,请将您想要在选择某个操作后运行的代码放在另一个函数中,然后在每个 UIAlertAction 处理程序的末尾调用该函数。

private var currentlyShowingAlert = false

@IBAction func buttonTapped(_ sender: Any) 

    if currentlyShowingAlert 

        return

    

    let alert = UIAlertController(title: "Ouch", message: "You didn't have to press me so hard!", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Sorry", style: .default, handler:  _ in
        self.handleAlert()
        self.alertCleanup()
    ))
    self.present(alert, animated: true, completion: nil)
    currentlyShowingAlert = true



func handleAlert() 

    print("UIAlertAction handler printed me")



func alertCleanup() 

     print("Should be printed last!")
     currentlyShowingAlert = false


在执行诸如推送视图控制器(或任何会堆叠调用的任何操作)以直接响应按钮按下等操作时要小心。 当主线程忙时,可以在第一次buttonTapped调用发生之前多次按下按钮,这样buttonTapped可以连续调用多次,currentlyShowingAlert会避免这个问题。

【讨论】:

以上是关于UIAlertController 没有立即显示的主要内容,如果未能解决你的问题,请参考以下文章

Swift UIAlertController 显示自定义消息

显示没有按钮的 UIAlertController 时 UI 测试失败

iOS - UIAlertController三种显示提示框代码

在最顶部的 UIViewController 上显示 UIAlertController

我有错误:“UIAlertController”没有可见界面

在演示过程中显示 UIAlertController