基于网络状态弹出/关闭UIAlertController在蜂窝数据下崩溃如何解决?
问题原因及修复方案
核心触发原因
- 你使用的
isBeingPresented判断条件逻辑存在缺陷:该属性仅在弹窗执行present动画的过程中为true,当弹窗完全展示在界面上后就会变为false。蜂窝网络切换时网络状态会短时间内连续触发多次回调,当第二次触发网络断开的逻辑时,isBeingPresented已经为false,代码会再次调用present方法尝试展示已经在视图层级中的弹窗,触发崩溃。 - 主队列操作错误使用了
DispatchQueue.main.sync:同步派发会阻塞当前网络监听队列,极端情况下会触发主队列死锁,同时连续状态变更的同步执行也会放大状态判断的误差。 - 没有对弹窗是否已经被添加到视图层级做判断:仅靠动画状态的判断无法覆盖所有场景,需要额外校验弹窗的
presentingViewController是否存在。
修复后的代码
class ViewController: UIViewController { var monitor = NWPathMonitor() let networkQueue = DispatchQueue(label: "InternetConnectionMonitor") var textInternet : Bool = true var internetPopUp : UIAlertController! override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) self.internetPopUp = UIAlertController(title: "Internet Connection", message: "Currently, the device is not connected to Internet, as soon as will be connected the alert will dissapear.", preferredStyle: .alert) startMonitoring() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 页面销毁时停止监听,避免内存泄漏 monitor.cancel() } //check internet connection func startMonitoring(){ monitor.pathUpdateHandler = { [weak self] path in guard let self = self else { return } let isSatisfied = path.status == .satisfied // 替换sync为async,避免死锁和队列阻塞 DispatchQueue.main.async { self.textInternet = isSatisfied self.pop() } } monitor.start(queue: networkQueue) } func pop(){ textInternet ? popDownAlert() : popUpAlert() } //func popUp Alert func popUpAlert(){ // 新增presentingViewController判断,避免重复present guard internetPopUp.presentingViewController == nil, !internetPopUp.isBeingPresented, !internetPopUp.isBeingDismissed else { return } present(internetPopUp, animated: true) } //func popDown Alert func popDownAlert() { guard internetPopUp.presentingViewController != nil, !internetPopUp.isBeingDismissed, !internetPopUp.isBeingPresented else { return } internetPopUp.dismiss(animated: true) } }
额外优化点
- 回调中增加了
[weak self]避免循环引用导致的内存泄漏 - 页面消失时调用
monitor.cancel()停止网络监听,释放资源 - 简化了状态判断逻辑,减少冗余代码
内容的提问来源于stack exchange,提问作者Mr Astronaut
相关产品推荐
相关产品推荐

