Swift新手求助:如何正确处理JSON解析错误?
解决Swift中URLSession请求的错误处理问题
Hey there! Let's figure out why your catch block isn't working and fix this properly.
问题根源
你遇到的两个核心问题:
try!导致错误无法抛出:try!是强制解码,一旦解码失败会直接触发运行时崩溃,而不是把错误抛给catch块处理。这也是编译器提示“catch块不可达”的原因——它看到你用了try!,认定do块里不会抛出任何可被捕获的错误。data!强制解包直接崩溃:如果API请求失败(比如超时、网络错误),data会是nil,这时候data!会直接崩溃,根本到不了do-catch的逻辑。
修复方案
我们需要分步骤处理所有可能的错误场景,同时用正确的方式抛出/捕获错误。
1. 定义自定义错误类型(可选但推荐)
先定义一个枚举来统一管理不同类型的错误,让错误处理更清晰:
enum APIError: Error { case noDataReceived // 请求成功但没返回数据 case requestFailed(Error) // 请求本身失败(比如网络问题) case decodingFailed(Error) // JSON解码失败 }
2. 修改请求处理逻辑
调整你的dataTask代码,完整处理所有错误分支:
// 假设你的completion闭包类型更新为Result类型,更规范 func fetchFiatRates(completion: @escaping (Result<FiatResponse, APIError>) -> Void) { guard let url = URL(string: "你的API地址") else { DispatchQueue.main.async { completion(.failure(.requestFailed(NSError(domain: "InvalidURL", code: -1, userInfo: nil)))) } return } URLSession.shared.dataTask(with: url) { data, _, error in // 第一步:处理请求本身的错误(比如超时、无网络) if let requestError = error { DispatchQueue.main.async { completion(.failure(.requestFailed(requestError))) } return } // 第二步:确保data不为nil guard let responseData = data else { DispatchQueue.main.async { completion(.failure(.noDataReceived)) } return } // 第三步:安全解码JSON,用try代替try! do { let fiatRates = try JSONDecoder().decode(FiatResponse.self, from: responseData) DispatchQueue.main.async { completion(.success(fiatRates)) } } catch let decodingError { DispatchQueue.main.async { completion(.failure(.decodingFailed(decodingError))) } } }.resume() }
3. 调用时的错误处理
当你调用这个方法时,就可以优雅地处理所有情况了:
fetchFiatRates { result in switch result { case .success(let rates): // 处理成功拿到的数据 print("Rates: \(rates.rates)") case .failure(let error): // 根据错误类型做对应处理 switch error { case .noDataReceived: print("请求成功但未收到数据") case .requestFailed(let underlyingError): print("请求失败:\(underlyingError.localizedDescription)") case .decodingFailed(let underlyingError): print("JSON解码失败:\(underlyingError.localizedDescription)") } } }
关键要点总结
- 永远避免用
try!和强制解包!处理网络请求相关的可选值,这些操作会把可恢复的错误变成致命崩溃。 - 必须先处理URLSession返回的
error参数,这是捕获网络层错误的关键。 - 用
try配合do-catch来处理解码错误,这样错误会被正确抛到catch块中处理。 - 所有UI相关的更新(包括completion回调)都要放在主队列
DispatchQueue.main.async中执行。
内容的提问来源于stack exchange,提问作者Reyraa
相关产品推荐
相关产品推荐

