ios uiwindow弹窗_iOS13.0版本以上新建UIWindow显示UIAlertController遇到的问题以及解决方式...

在iOS13及以上版本,直接使用UIWindow显示UIAlertController会出现闪现后消失的问题。解决方法是创建一个继承自UIAlertController的类,并在其中缓存UIWindow实例,以确保窗口不会被过早回收。此外,当使用UIViewController作为popover时,将新UIWindow的isUserInteractionEnabled设为false可以避免点击事件失效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在iOS中想在不依赖任何ViewController的情况下显示UIAlertController,在适配iOS13之前的写法是如下:

public func hhShowViewController(_ animated:Bool,completion: (() -> Void)?) {

let popWindow = UIWindow(frame:UIScreen.main.bounds)

popWindow.rootViewController = UIViewController()

popWindow.backgroundColor = UIColor.clear

popWindow.rootViewController?.view.backgroundColor = UIColor.clear

popWindow.windowLevel = UIWindow.Level.alert

popWindow.makeKeyAndVisible()

popWindow.rootViewController?.present(self, animated: animated, completion: completion)

}

其实很简单就是新创建一个UIWindow然后新建一个UIViewController设置为新UIWindow的rootViewController,然后使用这个Controller把UIViewController present出来,但发现在iOS13.0及以上版本就有问题了,弹框会出来一下,但是很快就又消失了,这个是个大bug,后来经过翻资料找到了解决方式,写法是新建一个类继承UIAlertController来,然后每次需要显示Alert的时候在类内缓存一下UIWIndow的实例,在弹框消失的时候置空就可以了。

import UIKit

public class HHAlertViewController: UIAlertController {

private var alertWindow:UIWindow?

public func showAlert(animated:Bool, completion:(()->Void)?) {

alertWindow = UIWindow(frame: UIScreen.main.bounds)

alertWindow?.rootViewController = UIViewController()

alertWindow?.windowLevel = UIWindow.Level.alert + 1

alertWindow?.makeKeyAndVisible()

alertWindow?.rootViewController?.present(self, animated: animated, completion: completion)

}

public override func viewDidDisappear(_ animated: Bool) {

super.viewDidDisappear(animated)

alertWindow = nil

}

}

对比两种代码是,第一种是在UIViewController的扩展里写的方法没法缓存UIWindow的实例,导致于刚显示出来又被很快回收了,造成的显示不正常。

补充一下:在写完这篇文章后我在用UIVIewController作为popover的时候这种写法会出现UIViewController内部的所有UI控件都无点击事件,经过一番尝试发现把新生成的UIWindow的isUserInteractionEnabled设置成false就可以了,我没有细究这个问题,我感觉应该是层级关系。下面贴出这个时候修正过的代码

import UIKit

open class HHConvenientVC: UIViewController {

private var alertWindow:UIWindow?

public func showVC(animated:Bool, completion:(()->Void)?) {

alertWindow = UIWindow(frame: UIScreen.main.bounds)

alertWindow?.rootViewController = UIViewController()

alertWindow?.isHidden = false

alertWindow?.windowLevel = UIWindow.Level.alert + 1

alertWindow?.makeKeyAndVisible()

alertWindow?.isUserInteractionEnabled = false //这行代码是解决这个事的重点

alertWindow?.rootViewController?.present(self, animated: animated, completion: completion)

}

public override func viewDidDisappear(_ animated: Bool) {

super.viewDidDisappear(animated)

alertWindow = nil

}

}

另外贴出popover的用法

在想用于popover的UIViewController的初始化加上如下代码

required init?(coder aDecoder: NSCoder)

{

super.init(coder: aDecoder)

self.modalPresentationStyle = .popover;

self.preferredContentSize = CGSize(width: 280, height: 265);

self.popoverPresentationController?.delegate = self

}

let controller = UIStoryboard(name: "DateSelector", bundle: Bundle(for: DateSelectorVC.self)).instantiateViewController(withIdentifier: "dateSelector") as? DateSelectorVC

controller?.mViewModel.mType = type

controller?.mViewModel.mSelect = select

let popController = controller?.popoverPresentationController

popController?.sourceView = sender

popController?.sourceRect = sender.bounds

popController?.permittedArrowDirections = [.up, .down]

controller?.showVC(animated: true, completion: nil)

1

1

vote

Article Rating

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值