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
相关产品推荐
相关产品推荐

