报错原因:
问题在于试图在一个 UIAlertController(已经显示的弹窗)上再展示另一个 UIAlertController。这在 iOS 中是不允许的,因为 UIAlertController 不能作为其他视图控制器的 presenter。
为了确保你的 AlertQueueManager 正确工作,并避免出现试图在非窗口层级中的视图控制器上展示新视图控制器的问题,我们需要确保每次只在最顶层的有效视图控制器上展示新的 UIAlertController。
class AlertQueueManager: NSObject {
static let shared = AlertQueueManager()
private var alertQueue: [(UIViewController) -> Void] = []
private var isShowing = false
private override init() {}
func enqueue(alertBuilder: @escaping (UIViewController) -> Void) {
DispatchQueue.main.async {
self.alertQueue.append(alertBuilder)
self.processNext()
}
}
private func processNext() {
guard !isShowing, let keyWindow = getKeyWindow(), let rootVC = keyWindow.rootViewController, !alertQueue.isEmpty else { return }
isShowing = true
let alertBuilder = alertQueue.removeFirst()
alertBuilder(rootVC)
}
func dequeue() {
isShowing = false
processNext()
}
private var topViewController: UIViewController? {
guard var top = getKeyWindow()?.rootViewController else { return nil }
while let presented = top.presentedViewController {
top = presented
}
return top
}
}
具体用法
et alert = UIAlertController(title: downloadTileInfo, message: "0%", preferredStyle: .alert)
let heightConstraint = NSLayoutConstraint(item: alert.view!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 200)
alert.view.addConstraint(heightConstraint)
// 添加进度条
let progressBar = UIProgressView(progressViewStyle: .default)
progressBar.translatesAutoresizingMaskIntoConstraints = false
alert.view.addSubview(progressBar)
progressBar.centerXAnchor.constraint(equalTo: alert.view.centerXAnchor).isActive = true
progressBar.centerYAnchor.constraint(equalTo: alert.view.centerYAnchor).isActive = true
progressBar.widthAnchor.constraint(equalToConstant: 200).isActive = true
let cancelAction = UIAlertAction(title: "取消", style: .cancel){[weak self] _ in
self?.cancelDownload()
}
alert.addAction(cancelAction)
// 入队
AlertQueueManager.shared.enqueue { viewController in
viewController.present(alert, animated: true) {
}
}
取消
DispatchQueue.main.async {
alert.dismiss(animated: true)
AlertQueueManager.shared.dequeue()
}
这是在处理多个弹窗的一点心得,与诸位共勉!!!希望能帮助需要的你