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

Swift中无法访问do-catch外变量及AlertController异常问题

解决UIAlertController无法访问JSON变量及主线程崩溃问题

我来帮你搞定这个问题!你的代码里有两个核心问题:异步任务的作用域和线程安全,咱们一步步拆解解决:

问题1:jsonmessage无法被外部的Alert访问

URLSession的dataTask是异步执行的——也就是说,你创建Alert的代码会在网络请求完成前就跑起来了,这时候jsonmessage还没被赋值,而且它的作用域只在if let parseJSON = myJSON这个代码块里,外部根本看不到它。

问题2:把Alert放进do块里崩溃

网络请求的回调是在后台线程执行的,而所有UI操作(比如present Alert)必须在主线程里做,直接在后台线程操作UI就会抛出你看到的NSException异常。

修正后的完整代码

request.httpBody = postParameters.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
    if let error = error {
        print("error is \(error)")
        // 网络错误时在主线程弹出提示
        DispatchQueue.main.async {
            let errorAlert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
            errorAlert.addAction(UIAlertAction(title: "Ok", style: .default))
            self.present(errorAlert, animated: true)
        }
        return
    }
    
    do {
        guard let data = data else {
            print("No data received")
            DispatchQueue.main.async {
                let emptyAlert = UIAlertController(title: "Alert", message: "No data received", preferredStyle: .alert)
                emptyAlert.addAction(UIAlertAction(title: "Ok", style: .default))
                self.present(emptyAlert, animated: true)
            }
            return
        }
        let myJSON = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary
        if let parseJSON = myJSON, let jsonmessage = parseJSON["message"] as? String {
            print(jsonmessage)
            // 切换到主线程执行UI操作
            DispatchQueue.main.async {
                let alert = UIAlertController(title: "Alert", message: jsonmessage, preferredStyle: .alert)
                alert.addAction(UIAlertAction(title:"Ok", style:.default, handler:{ _ in
                    _ = self.navigationController?.popToRootViewController(animated: true)
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
                }))
                self.present(alert, animated: true, completion: nil)
            }
        } else {
            // 处理JSON解析失败或message不存在的情况
            DispatchQueue.main.async {
                let invalidAlert = UIAlertController(title: "Alert", message: "Invalid response received", preferredStyle: .alert)
                invalidAlert.addAction(UIAlertAction(title: "Ok", style: .default))
                self.present(invalidAlert, animated: true)
            }
        }
    } catch {
        print("JSON parsing error: \(error)")
        DispatchQueue.main.async {
            let parseErrorAlert = UIAlertController(title: "Error", message: "Failed to parse response", preferredStyle: .alert)
            parseErrorAlert.addAction(UIAlertAction(title: "Ok", style: .default))
            self.present(parseErrorAlert, animated: true)
        }
    }
}
task.resume()

关键修改点说明

  • 线程切换:所有创建和present Alert的操作都用DispatchQueue.main.async包裹,确保在主线程执行UI操作,避免崩溃。
  • 作用域调整:把Alert的创建放在jsonmessage能被访问到的代码块里,确保变量已被正确赋值。
  • 可选值安全处理:用guard let和if let替代强制解包(!),避免因数据为空或类型不匹配导致的崩溃。
  • 错误分支处理:给每个可能出错的情况(网络错误、无数据、解析失败、message不存在)都添加了对应的Alert提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:00:59