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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:15:03