SWIFT TASK CONTINUATION MISUSE:泄露了它的延续

Posted

技术标签:

【中文标题】SWIFT TASK CONTINUATION MISUSE:泄露了它的延续【英文标题】:SWIFT TASK CONTINUATION MISUSE: leaked its continuation 【发布时间】:2022-01-21 05:54:18 【问题描述】:

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

func afRequest(url: URL) async throws -> Data 
    try await withCheckedThrowingContinuation  continuation in
        // timeoutInterval is in seconds
        AF.request(url, method: .get, requestModifier:  $0.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:  $0.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
            
            
        
    

【问题讨论】:

更新到 Alamofire 5.5 以获得内置 async - await 支持。 我已经升级了,但看不出有什么不同,你能发布一个带有错误处理的新异步函数的解决方案吗? @JonShier 您可以阅读文档:github.com/Alamofire/Alamofire/blob/master/Documentation/… 在发帖之前我已经做过了,没有一个清晰完整的例子来说明如何做到这一点@JonShier 文档中有几个例子,我不确定你的意思。 AF.request(...).serializingData() 让您可以像这里一样访问可等待的 API。 【参考方案1】:

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

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

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

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

【讨论】:

我将其更改为:if case let .failure(error) = response.result 并将 switch 语句放入其中,并在最后继续抛出并返回,但仍然如此:/ 从所有分支调用延续是什么意思? 在答案中添加了更多细节 我更改了它,但它说的一样,请参阅上面编辑下我编辑的问题。 这看起来有同样的问题。您需要确保逻辑中的每个分支都调用延续。您所做的更改仅在失败的情况下调用延续。您需要在 if 语句中添加 else 并在其中调用 continuation。

以上是关于SWIFT TASK CONTINUATION MISUSE:泄露了它的延续的主要内容,如果未能解决你的问题,请参考以下文章

.Net 中的多任务

理解 Continuation

task.arguments 中的 Swift 参数

android kotlin 协程 suspend与continuation

.task 崩溃 - Swift 5.5 (iOS 15 Beta 5)

task.arguments中的Swift参数