【问题标题】:Dispatch asyncAfter for multiple UIAlertControllers为多个 UIAlertControllers 调度 asyncAfter
【发布时间】:2017-06-26 15:34:28
【问题描述】:

我有一个异步调度,我希望屏幕上会弹出 4 个警报。然后每个警报都会在显示新警报之前被解除。 (我在警报之间设置了 3 秒延迟)

class ViewController: UIViewController {

    var counter = 1

    override func viewDidLoad() {
        super.viewDidLoad()

        for _ in 1...4{
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.0 * Double(counter)  , execute: {
                print("called")
                self.showAlert()
            })
        }
    }

    func showAlert(){

        let alert = UIAlertController(title: "sampleTitle \(counter)", message: "sampleMessage \(counter)", preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)

        counter += 1
        if self.presentedViewController != nil {
            dismiss(animated: true, completion: nil)
            UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
        }else{
            UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
        }
    }
}

问题1:但由于某种原因,整个for loop 被执行,中间没有任何延迟。我猜我不理解主队列是串行队列的一些事情。

问题 2: 即使我关闭了presentedViewController,我也会在控制台中获得以下日志。

called
called
called
called
2017-06-26 11:10:57.000 topViewAndAlertTest[3360:210226] Warning: Attempt to dismiss from view controller <topViewAndAlertTest.ViewController: 0x7fe630c03350> while a presentation or dismiss is in progress!
2017-06-26 11:10:57.001 topViewAndAlertTest[3360:210226] Warning: Attempt to present <UIAlertController: 0x7fe630c04180> on <UIAlertController: 0x7fe630f06fe0> while a presentation is in progress!
2017-06-26 11:10:57.001 topViewAndAlertTest[3360:210226] Warning: Attempt to dismiss from view controller <topViewAndAlertTest.ViewController: 0x7fe630c03350> while a presentation or dismiss is in progress!
2017-06-26 11:10:57.001 topViewAndAlertTest[3360:210226] Warning: Attempt to present <UIAlertController: 0x7fe630c06b40> on <UIAlertController: 0x7fe630f06fe0> while a presentation is in progress!

仅供参考,我的 topviewcontroller 正在使用来自 answer 的代码

问题 3:只有 2 个警报弹出...我从来没有看到第 3、4 个警报!


编辑:

经过rmaddy的建议,我的错误略有改变:

called
called
called
called
2017-06-26 11:59:33.417 topViewAndAlertTest[4834:441163] Warning: Attempt to dismiss from view controller <topViewAndAlertTest.ViewController: 0x7fb596d05a30> while a presentation or dismiss is in progress!
2017-06-26 11:59:33.417 topViewAndAlertTest[4834:441163] Warning: Attempt to dismiss from view controller <topViewAndAlertTest.ViewController: 0x7fb596d05a30> while a presentation or dismiss is in progress!

我少收到 2 个警告。但仍然:一旦警报 1 出现在屏幕上,警报 2 就会将其关闭,仅此而已!没有延迟没有第三,第四警报!

【问题讨论】:

    标签: ios swift grand-central-dispatch uialertcontroller dispatch-async


    【解决方案1】:

    详情

    xCode 8.3.2,斯威夫特 3.1

    完整代码

    import UIKit
    
    class ViewController: UIViewController {
    
        var counter = 1
    
        private var alertViewController: UIAlertController?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            DispatchQueue.global(qos: .utility).async {
                for _ in 1...4 {
                    sleep(2)
                    DispatchQueue.main.async {
                        print("called")
                        self.showAlert()
                    }
                }
            }
        }
    
        private func createAlertView() -> UIAlertController {
            let alertViewController = UIAlertController(title: "sampleTitle \(counter)", message: "sampleMessage \(counter)", preferredStyle: .alert)
            let action = UIAlertAction(title: "OK", style: .default, handler: nil)
            alertViewController.addAction(action)
            return alertViewController
        }
    
        func showAlert(){
    
            let presentAlert = {
                DispatchQueue.main.async { [weak self] in
                    if let _self = self {
                        _self.alertViewController = _self.createAlertView()
                        UIApplication.topViewController()?.present(_self.alertViewController!, animated: true, completion: nil)
                    }
                }
            }
    
            DispatchQueue.main.async { [weak self] in
                if let alertViewController = self?.alertViewController {
                    alertViewController.dismiss(animated: true) {
                        presentAlert()
                    }
                } else {
                    presentAlert()
                }
                self?.counter += 1
            }
        }
    }
    
    extension UIApplication {
        class func topViewController(base: UIViewController? = (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
            if let nav = base as? UINavigationController {
                return topViewController(base: nav.visibleViewController)
            }
            if let tab = base as? UITabBarController {
                if let selected = tab.selectedViewController {
                    return topViewController(base: selected)
                }
            }
            if let presented = base?.presentedViewController {
                return topViewController(base: presented)
            }
            return base
        }
    }
    

    【讨论】:

    • 赞成。这行得通。但我也在试图弄清楚为什么我的不起作用。关于为什么不这样做的任何想法?
    • 在 viewDidLoad 您试图创建 4 个不同时间的事件,但您的代码几乎同时生成 4 个动作。尝试使用这个示例(动作之间的时间差)var previousTime = DispatchTime(uptimeNanoseconds: 0) for _ in 1...4{ let time = DispatchTime.now() + 3.0 * Double(counter) if previousTime.uptimeNanoseconds != 0 { print("different: \(Double(time.uptimeNanoseconds - previousTime.uptimeNanoseconds)/100_000.0) uSeconds") } previousTime = time }
    • 我们可以尝试许多不同的解决方案:D 我只是不明白为什么我的代码会同时创建 4 个操作。你能解释一下吗?
    • 因为您的函数 viewDidLoad 和该函数内部的循环在第一次关闭 DispatchQueue.main.asyncAfter 开始之前完成。所以,让你的代码分开 [.now() + 3.0 * Double(counter)]。 3.0 * Double(counter) - 这在 viewDidLoad 中不会改变(它在 viewDidLoad 中将具有相同的值),.now() 的差异将小于 1 秒。这意味着,在您的循环中.now() + 3.0 * Double(counter) - 一个时间段
    猜你喜欢
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多