UIAlertAction处理程序/闭包在failure分支不执行问题求助
问题分析与解决方案
核心原因
最可能的情况是:failure分支执行时,当前视图控制器(self)已经被释放。比如网络请求失败的响应速度很快,用户在请求过程中已经导航离开当前页面,导致视图控制器被销毁。此时虽然弹窗能正常显示,但点击OK按钮时,闭包捕获的self已不存在,代码自然无法执行;而success分支的请求耗时较长,用户仍停留在当前页面,self未被释放,因此闭包能正常运行。
解决方案
1. 确保UI操作在主线程执行
Task中await后的代码不一定在主线程运行,所有UI相关操作必须切换到主线程执行,避免线程不一致引发的问题。
2. 弱引用视图控制器,避免循环引用与无效操作
在弹窗的闭包和showModal方法中对self使用弱引用,既可以避免循环引用,也能在self已释放时跳过无效代码。
修改后的代码示例
优化UIViewController扩展
extension UIViewController { func showModal(title: String, msg: String, handler: ((UIAlertAction) -> Void)? = nil) { let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: handler)) DispatchQueue.main.async { [weak self] in // 仅当self存在时才present弹窗 self?.present(alert, animated: true, completion: nil) } } }
优化按钮点击事件逻辑
@IBAction func didTapSave(_ sender: UIButton) { Task { let result = await BalanceManager.shared.fetchAllBalances() // 切换到主线程处理UI操作 DispatchQueue.main.async { [weak self] in guard let self = self else { return } switch result { case .success(_): self.showModal(title: "", msg: "account successfully saved") { [weak self] _ in self?.navigationController?.popViewController(animated: true) } case .failure(let failure): self.showModal(title: "", msg: "failure") { _ in print("Failure closure") } } } } }
可选:验证视图控制器是否被释放
可以在视图控制器中添加deinit方法,确认是否因页面导航导致控制器被销毁:
deinit { print("\(self) 已被销毁") }
内容的提问来源于stack exchange,提问作者cvld
相关产品推荐
相关产品推荐

