iOS开发中远程GET请求失败时如何设置兜底降级方案?
问题根源
- 你当前用的
do-catch完全无效:getRemoteJson是异步回调方法,调用时不会同步抛出错误,代码执行到getRemoteJson之后会立刻走完do块,根本不会触发catch分支 getRemoteJson的实现存在逻辑漏洞:请求报错、无返回数据、HTTP状态码异常时,你都没有触发completion回调,上层无法感知请求失败,自然不会走本地兜底逻辑- 回调参数设计不合理:仅返回可选
Data,没有携带错误信息,上层无法区分「请求成功但数据为空」和「请求失败」的场景 - 多处强制解包(
remoteJson!、localFile!)存在崩溃风险
修复方案
第一步:重构getRemoteJson方法
调整回调参数,确保所有场景都触发回调,同时透传错误信息:
private func getRemoteJson(requestUrl: URL, requestType: String, completion: @escaping (Result<Data, Error>) -> Void) { var request = URLRequest(url: requestUrl) request.httpMethod = requestType let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // 先处理系统级错误(无网络、超时等) if let error = error { completion(.failure(error)) return } // 校验HTTP状态码为2xx区间 guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode), let data = data else { // 构造自定义错误,也可以自己定义错误枚举 let requestError = NSError(domain: "RemoteRequestError", code: -1, userInfo: [NSLocalizedDescriptionKey: "请求无效或无返回数据"]) completion(.failure(requestError)) return } completion(.success(data)) } task.resume() }
第二步:调整调用逻辑,移除无效的外层do-catch
所有异常场景(请求失败、解析失败)都走本地JSON兜底:
guard let url = URL(string: "https://jsontestlocation.com") else { // 链接无效直接走本地兜底 loadLocalJsonFallback() return } getRemoteJson(requestUrl: url, requestType: "GET") { [weak self] result in guard let self = self else { return } switch result { case .success(let remoteData): if let remoteJson = self.parseJson(jsonData: remoteData) { performOnMainThread { self.delegate.value?.didReceiveJson(.success(remoteJson)) } } else { // 远端JSON解析失败,走本地兜底 self.loadLocalJsonFallback() } case .failure(_): // 请求失败,走本地兜底 self.loadLocalJsonFallback() } } // 单独抽离本地兜底逻辑 private func loadLocalJsonFallback() { guard let localFile = readLocalFile(forName: "local_json_file"), let localJson = parseJson(jsonData: localFile) else { // 本地文件读取/解析失败的话可以在这里抛错误给上层 performOnMainThread { self.delegate.value?.didReceiveJson(.failure(NSError(domain: "LocalJsonError", code: -2, userInfo: nil))) } return } performOnMainThread { self.delegate.value?.didReceiveJson(.success(localJson)) } }
可选优化
- 可以提前通过网络状态判断工具检测当前网络,无网络时直接走本地逻辑,减少不必要的请求
- 可以给远端请求加缓存,下次启动时如果请求失败可以优先用上次缓存的远端数据,再降级到本地静态JSON
内容的提问来源于stack exchange,提问作者John Szatmari
相关产品推荐
相关产品推荐

