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) } } } }
关键修复点说明
- 覆盖所有错误分支:不再只处理单个
AFErrorcase,而是通过外层的.failure捕获所有错误,保证任何错误都会触发continuation.resume(throwing:)。 - 优先处理
response.result:response.result已经封装了请求的最终状态,比单独判断response.data更可靠——因为.success里的data已经通过了validate的校验,是有效的。 - 添加异常状态保护:虽然理论上
response.result只会是success或failure,但添加continuation.isResumed检查可以避免极端情况下的泄漏。
之前修改的问题分析
- 修改1:依然只处理了
.invalidURL,其他错误(比如超时)还是没触发resume,泄漏问题依旧。 - 修改2:
continuation.resume(throwing: Error.self as! Error)是错误的写法——你不能把Error类型强转为错误实例,必须传递一个具体的错误对象,这会导致运行时崩溃。
内容的提问来源于stack exchange,提问作者Arturo
相关产品推荐
相关产品推荐

