如何在单个UIViewController中通过按钮点击调用并显示多个自定义Alert视图?
如何在单个ViewController上同时显示两个自定义Alert
首先看你当前代码里的几个关键问题,这些问题会导致你无法同时显示两个Alert,甚至第一个Alert都可能显示异常:
- 过时的
keyWindow用法:iOS13+之后UIApplication.shared.keyWindow已经被废弃,而且直接把Alert加到keyWindow上,不如加到当前ViewController的view层级里更可控。 - 单例的错误使用:自定义Alert用单例的话,每次调用
ShowAlert都会重复添加同一个parentView到视图层级,导致重复显示或者状态混乱,应该每次创建新的实例。 - 布局初始化错误:
CommonInit方法里的frame设置有问题,比如FirstCustomAlert里的alertView(应该是parentView?)frame起点用了center.x和center.y,这会让你的Alert视图偏移到屏幕外;而且SecondCustomAlert的CommonInit根本没被调用,导致布局没生效。 - 多余的
dismiss调用:ViewControllerA里的self.dismiss(animated: true, completion: nil)会把当前VC关掉,反而看不到Alert,应该删掉。
下面是修复后的完整代码,我会标注关键修改点:
修复后的ViewControllerA
class ViewControllerA : UIViewController{ @IBAction func ViewControllerAButtonTapped(_ sender: Any) { // 创建FirstCustomAlert的新实例,而非单例 let firstAlert = FirstCustomAlert() // 把Alert加到当前VC的view上,替代keyWindow firstAlert.showAlert(on: self.view) // 移除多余的dismiss调用 } }
修复后的FirstCustomAlert
class FirstCustomAlert : UIView{ @IBOutlet var parentView: UIView! @IBOutlet weak var firstTextField: UITextField! override init(frame: CGRect) { super.init(frame: frame) Bundle.main.loadNibNamed("FirstCustomAlert", owner: self, options: nil) commonInit() // 调用初始化方法 } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func commonInit(){ // 正确设置parentView的frame,铺满整个自定义View parentView.frame = bounds parentView.autoresizingMask = [.flexibleHeight, .flexibleWidth] // 将parentView添加到当前自定义View上 addSubview(parentView) } // 修改方法参数,接收要添加到的父视图 func showAlert(on parentView: UIView){ // 设置当前自定义View的frame为父视图的bounds self.frame = parentView.bounds self.autoresizingMask = [.flexibleHeight, .flexibleWidth] parentView.addSubview(self) } @IBAction func SubmitBittonTapped(_ sender: Any) { // 创建SecondCustomAlert的新实例 let secondAlert = SecondCustomAlert() // 把第二个Alert加到同一个父视图(ViewControllerA的view)上 secondAlert.showAlert(on: self.superview!) } }
修复后的SecondCustomAlert
class SecondCustomAlert : UIView{ @IBOutlet var parentView: UIView! @IBOutlet weak var secondTextField: UITextField! override init(frame: CGRect) { super.init(frame: frame) Bundle.main.loadNibNamed("SecondCustomAlert", owner: self, options: nil) commonInit() // 现在调用初始化方法了 } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func commonInit(){ parentView.frame = bounds parentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(parentView) } func showAlert(on parentView: UIView){ self.frame = parentView.bounds self.autoresizingMask = [.flexibleHeight, .flexibleWidth] parentView.addSubview(self) } }
关键修改说明
- 移除单例模式:每次需要显示Alert时创建新实例,避免重复添加同一视图和状态混乱。
- 调整视图层级:将自定义Alert加到当前ViewController的view上,层级更清晰,符合iOS视图管理规范。
- 修复布局初始化:确保
commonInit被调用,正确设置parentView的frame和autoresizingMask,让Alert能适配父视图(你也可以根据需求改成居中弹窗样式)。 - 删除无效dismiss:ViewControllerA里的dismiss会关闭自身,导致无法看到Alert,因此移除该代码。
修改后,点击ViewControllerA的按钮会显示第一个Alert;点击第一个Alert的提交按钮,第二个Alert会叠加显示在第一个上面,两个Alert都处于ViewControllerA的视图层级中,就能实现你想要的同时显示效果了。
内容的提问来源于stack exchange,提问作者Ronak Patel
相关产品推荐
相关产品推荐

