You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:10:45