SWIFT 任务延续误用:泄露了它的延续

SWIFT TASK CONTINUATION MISUSE: leaked its continuation

我正在使用以下函数通过 Alamofire 执行获取请求:

func afRequest(url: URL) async throws -> Data {
    try await withCheckedThrowingContinuation { continuation in
        // timeoutInterval is in seconds
        AF.request(url, method: .get, requestModifier: { [=11=].timeoutInterval = 10 }).validate(statusCode: 200..<600).responseData { response in
            
            if let data = response.data {
                continuation.resume(returning: data)
                return
            }
            
            guard case let .failure(error) = response.result else { return }
            
            switch error {
                case .invalidURL(let url):
                    print("Invalid URL: \(url) - \(error.localizedDescription)")
                    
                    continuation.resume(throwing: error)
            }
        }
    }
}

我特意将超时设置为 10 秒来进行测试。所以错误是"The request timed out."。之后我得到这个错误:

SWIFT TASK CONTINUATION MISUSE: afRequest(url:) leaked its continuation!

我正在查看 this post,但不清楚他们完成了什么或解决方案。减轻这种泄漏的正确方法是什么?

编辑:

上面的部分我是这样切换的,但还是一样:

if case let .failure(error) = response.result {
    switch error {
        case .invalidURL(let url):
        ...

    continuation.resume(throwing: error)
    return

编辑 2 - 这是错误的新处理方式,但还是一样:

func afRequest(url: URL) async throws -> Data {
    try await withCheckedThrowingContinuation { continuation in
        // timeoutInterval is in seconds
        AF.request(url, method: .get, requestModifier: { [=14=].timeoutInterval = .infinity }).validate(statusCode: 200..<600).responseData { response in
            
            if let data = response.data {
                continuation.resume(returning: data)
                return
            }
            
            if case let .failure(error) = response.result {
                switch error {
                    case .invalidURL(let url):
                        print("Invalid URL: \(url) - \(error.localizedDescription)")
                   // There are more cases...
                        
                        continuation.resume(throwing: error)
                        return
                }
            }
            else {
                  continuation.resume(throwing: Error.self as! Error)
                  return
            }
            
        }
    }
}

你的守卫正在捕获一个案例,而不是调用继续。您需要从所有分支调用延续(例如 continuation.resume(...)),以免泄漏。

这个早期 return 导致了这个问题

guard case let .failure(error) = response.result else { return }

在您的示例中,您需要决定如何处理 response.data 为零和 response.result 为成功,然后更新您的 guard 以适当地调用 continuation.resume(...)