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

Swift Task Continuation误用问题:Alamofire异步请求中Continuation泄漏的解决方案

解决SWIFT TASK CONTINUATION MISUSE泄漏问题

你的问题核心在于没有覆盖Alamofire请求的所有可能结果分支,导致某些错误(比如你测试的超时)发生时,continuation从未被调用resume(),最终引发泄漏警告。

问题根源分析

Alamofire的AFError包含多个错误case,比如:

  • .invalidURL(你处理的)
  • .sessionTaskFailed(包含超时、网络连接失败等底层错误)
  • .responseValidationFailed(状态码不符合validate规则)
  • 还有序列化错误、参数编码错误等其他类型

你之前的代码只处理了.invalidURL这一种错误,像超时这类属于.sessionTaskFailed的错误根本没被捕获,continuation就一直处于挂起状态,最终触发泄漏警告。

正确的修复方案

我们需要确保无论请求结果是成功、任何类型的错误,甚至极端的未知状态,都必须调用continuation.resume()。下面是修正后的完整代码:

func afRequest(url: URL) async throws -> Data {
    try await withCheckedThrowingContinuation { continuation in
        // 设置10秒超时
        AF.request(url, method: .get, requestModifier: { $0.timeoutInterval = 10 })
            .validate(statusCode: 200..<600)
            .responseData { response in
                // 优先处理result,它已经封装了成功/失败的完整状态
                switch response.result {
                case .success(let data):
                    // 成功时返回数据
                    continuation.resume(returning: data)
                case .failure(let error):
                    // 可以根据需要针对性处理不同的AFError类型
                    switch error {
                    case .invalidURL(let url):
                        print("Invalid URL: \(url) - \(error.localizedDescription)")
                    case .sessionTaskFailed(let underlyingError):
                        if (underlyingError as NSError).code == NSURLErrorTimedOut {
                            print("Request timed out after 10 seconds")
                        }
                    case .responseValidationFailed(let reason):
                        print("Status code validation failed: \(reason)")
                    // 其他错误case可以按需添加
                    default:
                        print("Request failed: \(error.localizedDescription)")
                    }
                    
                    // 关键:所有错误都必须resume,抛出对应的错误
                    continuation.resume(throwing: error)
                }
                
                // 极端保险:防止result出现既不是success也不是failure的异常情况
                if !continuation.isResumed {
                    let unknownError = NSError(
                        domain: "com.yourapp.network",
                        code: -999,
                        userInfo: [NSLocalizedDescriptionKey: "Unexpected request state"]
                    )
                    continuation.resume(throwing: unknownError)
                }
            }
    }
}

关键修复点说明

  1. 覆盖所有错误分支:不再只处理单个AFError case,而是通过外层的.failure捕获所有错误,保证任何错误都会触发continuation.resume(throwing:)。
  2. 优先处理response.result:response.result已经封装了请求的最终状态,比单独判断response.data更可靠——因为.success里的data已经通过了validate的校验,是有效的。
  3. 添加异常状态保护:虽然理论上response.result只会是success或failure,但添加continuation.isResumed检查可以避免极端情况下的泄漏。

之前修改的问题分析

  • 修改1:依然只处理了.invalidURL,其他错误(比如超时)还是没触发resume,泄漏问题依旧。
  • 修改2:continuation.resume(throwing: Error.self as! Error)是错误的写法——你不能把Error类型强转为错误实例,必须传递一个具体的错误对象,这会导致运行时崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 03:27:39