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

Swift 5.5适配async/await做API请求偶现NSURLErrorDomain -999错误

错误触发原因
  • SwiftUI的.task修饰符默认和所属视图的生命周期绑定,当视图在请求完成前被销毁/重绘时,修饰符管理的异步任务会自动被取消,Swift Concurrency体系下被取消的任务会自动终止正在执行的网络请求,抛出NSURLErrorDomain Code=-999错误。而你之前用的dataTask闭包实现不受视图生命周期管控,即使视图销毁也会继续执行完成,所以不会出现这类取消错误。
  • 你在API单例的初始化方法中修改URLSession.shared的配置属于无效操作,URLSession.shared的配置是只读属性,修改它不会生效,甚至可能引发未定义的网络行为,增加偶现问题的概率。
  • 你当前的请求逻辑没有做任务取消的兼容处理,一旦任务被取消就直接触发fatalError,没有容错空间。
解决方案
    1. 优化.task修饰符的使用:给.task绑定固定的唯一标识,避免视图非必要重绘时反复取消重建任务,示例修改如下:
.task(id: "init_api_request") { // 绑定固定id,只要id不变就不会取消现有任务
    let api = API.singleton
    await api.makeAuthorization()
    await api.getTestConfiguration()
}

如果业务允许请求不受视图生命周期影响,也可以将请求逻辑移到全局的业务管理类/StateObject中执行,避免和视图生命周期绑定。

    1. 替换全局共享URLSession,自定义独立的URLSession实例,正确配置超时参数:
      在API类中新增自定义session属性,不要修改shared的配置:
// 替换原来直接修改URLSession.shared的逻辑
private let session: URLSession = {
    let config = URLSessionConfiguration.default
    config.timeoutIntervalForRequest = 530.0
    config.timeoutIntervalForResource = 560.0
    return URLSession(configuration: config)
}()

所有网络请求的地方都用这个自定义的session代替URLSession.shared。

    1. 添加取消错误的兼容处理,不要直接抛出fatalError,可以根据业务需求选择忽略取消、自动重试或者提示用户:
// 示例捕获取消错误的逻辑
do {
    let (data, response) = try await session.data(for: request)
    // 原有请求成功处理逻辑
} catch let error as URLError where error.code == .cancelled {
    print("请求被取消,可根据业务处理:比如静默忽略、触发重试")
} catch {
    fatalError("请求失败: \(error)")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 04:39:00