如何使用Async/Await在Swift中进行进度报告?

7
我有一个需要传入2个回调函数的函数,我想将其转换为async/await。但是如何在不断返回进度的同时等待呢? 我正在使用https://github.com/yannickl/AwaitKit来摆脱回调函数。
 typealias GetResultCallBack = (String) -> Void
 typealias ProgressCallBack = (Double) -> Void
   
 
func getFileFromS3(onComplete callBack: @escaping GetResultCallBack,
                  progress progressCallback: @escaping ProgressCallBack) {

}

我是这样使用它的:

getFileFromS3() { [weak self] (result) in
        guard let self = self else { return }
        
       // Do something with result
        
    } progress: { [weak self] (progress) in
        guard let self = self else { return }
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else {return}
            // Update progress in UI     
        }
        
    }

以下是没有进度报告的转换代码:

func getFileFromS3() -> Promise<String> {  
  return async {

  //  return here
  }
}
2个回答

6
你可以使用类似这样的技术:
从签名中可以看出,您可以使用Data(_:)方法设置请求体。
func data(for request: URLRequest, 
          delegate: URLSessionTaskDelegate? = nil) async throws 
              -> (Data, URLResponse)

这个方法是异步的,但也需要一个委托对象:

https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate

正如您所看到的,该委托对象接收任务进度的回调。您可以声明类似的内容,并将从委托传递的信息提供给主要的Actor和界面。


谢谢,@matt提供的答案。我使用了类似的技术,通过使用委托,在等待时能够更新进度。 - M Afham

1

我花了一些时间,但终于取得了这个结果,首先你必须设置一个委托来开始这个任务:

let (data, _) = try await URLSession.shared.data(for: .init(url: url), delegate: self)

在您的委托中,您订阅了进度更新:
 public func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) {
    progressObservation = task.progress.observe(\.fractionCompleted) { progress, value in
        print("progress: ", progress.fractionCompleted)
    }
}

不要忘记,“progressObservation”需要是一个强引用。

我非常确定这就是我的答案所表达的意思。 - matt
2
在我看来,知道使用哪个委托方法以及如何使用它也是有益的。顺便说一句,我用了你的答案来找出如何做到这一点,所以...谢谢 :) - Bruno Pantaleão

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接