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

异步函数中UIAlertController无法正常关闭的问题求助

解决思路

核心问题定位

错误提示的本质是弹窗 Dismiss 操作未完成时,就触发了新弹窗的 Present 操作。UIAlertController的dismiss(animated:completion:)是异步执行的——即便调用了dismiss方法,界面上的弹窗不会立刻消失,必须等其动画(或非动画的收尾逻辑)完成后,才能执行新的弹窗展示操作。你之前的失败场景就是因为跳过了这个等待过程,直接触发了新弹窗。

具体修复方案

1. 用 Dismiss 的 Completion 回调控制时序

不管成功还是失败场景,都把新弹窗的展示逻辑放在原加载弹窗dismiss方法的completion闭包里,确保原弹窗完全消失后再执行后续操作:

// 假设loadingAlert是你创建的加载弹窗实例
loadingAlert.dismiss(animated: true) { [weak self] in
    guard let self = self else { return }
    let processedString = dataString.trimmingCharacters(in: .newlines)
    if processedString == "no valid userID" {
        let errorAlert = UIAlertController(title: "提示", message: "无效的用户ID", preferredStyle: .alert)
        errorAlert.addAction(UIAlertAction(title: "确定", style: .default))
        self.present(errorAlert, animated: true)
    } else {
        let successAlert = UIAlertController(title: "成功", message: "上传完成", preferredStyle: .alert)
        successAlert.addAction(UIAlertAction(title: "确定", style: .default))
        self.present(successAlert, animated: true)
    }
}

2. 废弃didSet监听的方案

你之前用didSet触发弹窗关闭,但didSet只是同步执行了dismiss调用,没有等待dismiss完成就去present新弹窗,这才导致时序冲突。改用上述completion回调的方式,能严格保证操作顺序。

3. 强制UI操作在主线程执行

异步网络请求的回调默认在后台线程,必须切换到主线程处理UI操作,否则可能出现不可预期的问题:

// 网络请求回调中切换到主线程
DispatchQueue.main.async {
    // 这里执行弹窗的dismiss和present操作
}

4. 避免循环引用

在闭包中捕获self时,一定要用[weak self]弱引用,防止内存泄漏。

内容的提问来源于stack exchange,提问作者blendstylez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:40:06