我想创建一个帮助类,用于展示UIAlertController
。由于它是一个辅助类,我希望它能够在任何视图层次结构中使用,而且不需要关于视图的任何信息。我可以显示警告,但当警告被取消时,应用程序崩溃并出现以下错误:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Trying to dismiss UIAlertController <UIAlertController: 0x135d70d80>
with unknown presenter.'
我正在使用以下代码创建弹出窗口:
guard let window = UIApplication.shared.keyWindow else { return }
let view = UIView()
view.isUserInteractionEnabled = true
window.insertSubview(view, at: 0)
window.bringSubview(toFront: view)
// add full screen constraints to view ...
let controller = UIAlertController(
title: "confirm deletion?",
message: ":)",
preferredStyle: .alert
)
let deleteAction = UIAlertAction(
title: "yes",
style: .destructive,
handler: { _ in
DispatchQueue.main.async {
view.removeFromSuperview()
completion()
}
}
)
controller.addAction(deleteAction)
view.insertSubview(controller.view, at: 0)
view.bringSubview(toFront: controller.view)
// add centering constraints to controller.view ...
当我点击yes
时,应用程序会崩溃并且处理程序在崩溃之前没有被触发。我无法呈现UIAlertController
,因为这将取决于当前视图层次结构,而我希望弹出窗口是独立的。
编辑:Swift解决方案 感谢@Vlad提供的想法。似乎在单独的窗口中操作要简单得多。所以这里是一个可行的Swift解决方案:
class Popup {
private var alertWindow: UIWindow
static var shared = Popup()
init() {
alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindowLevelAlert + 1
alertWindow.makeKeyAndVisible()
alertWindow.isHidden = true
}
private func show(completion: @escaping ((Bool) -> Void)) {
let controller = UIAlertController(
title: "Want to do it?",
message: "message",
preferredStyle: .alert
)
let yesAction = UIAlertAction(
title: "Yes",
style: .default,
handler: { _ in
DispatchQueue.main.async {
self.alertWindow.isHidden = true
completion(true)
}
})
let noAction = UIAlertAction(
title: "Not now",
style: .destructive,
handler: { _ in
DispatchQueue.main.async {
self.alertWindow.isHidden = true
completion(false)
}
})
controller.addAction(noAction)
controller.addAction(yesAction)
self.alertWindow.isHidden = false
alertWindow.rootViewController?.present(controller, animated: false)
}
}