popover页面中关闭UIAlertController无反应或误关整个弹窗如何解决
问题根因
- 你当前的实现每次调用
presentLoadingView都会创建全新的UIAlertController实例:当你传入shouldPresent = false试图关闭加载框时,你dismiss的是刚刚新建、还未弹出的alert实例,之前已经展示在界面上的alert没有被持有引用,自然无法响应dismiss操作 - 直接调用无前缀的
dismiss(animated: true)会触发当前ViewController(也就是你的popover本身)的dismiss方法,所以会把整个popover关掉
解决方案
首先在你的popover对应的ViewController中,新增一个私有属性持有加载弹窗的引用:
// 持有加载弹窗的全局引用 private var loadingAlert: UIAlertController?
然后修改presentLoadingView的实现逻辑,分开处理弹出和关闭的场景:
private func presentLoadingView(shouldPresent: Bool) { // 强制主队列执行UI操作,避免CoreData异步操作导致UI调用不在主队列的问题 DispatchQueue.main.async { [weak self] in guard let self = self else { return } if shouldPresent { // 避免重复弹出加载框 guard self.loadingAlert == nil else { return } let alert = UIAlertController(title: nil, message: "Retrieving Owner Data", preferredStyle: .alert) let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) loadingIndicator.hidesWhenStopped = true loadingIndicator.style = .medium loadingIndicator.startAnimating() alert.view.addSubview(loadingIndicator) // 存储弹窗引用 self.loadingAlert = alert // 如果有自定义的presentAnimated方法可替换下方系统方法 self.present(alert, animated: true) } else { // 用之前持有的引用关闭弹窗 self.loadingAlert?.dismiss(animated: true) // 引用置空,避免下次调用出现判断异常 self.loadingAlert = nil } } }
使用方式
- CoreData操作开始前调用
presentLoadingView(shouldPresent: true)弹出加载框 - CoreData异步操作完成的回调中调用
presentLoadingView(shouldPresent: false)关闭加载框即可
内容的提问来源于stack exchange,提问作者Martin sku
相关产品推荐
相关产品推荐

