简体   繁体   中英

How to do progress reporting using Async/Await swift?

I have a function that takes 2 callbacks. I want to convert this into async/await. But how can I await while continuously returning the progress also? I am using https://github.com/yannickl/AwaitKit to get rid of callbacks.

 typealias GetResultCallBack = (String) -> Void
 typealias ProgressCallBack = (Double) -> Void
   
 
func getFileFromS3(onComplete callBack: @escaping GetResultCallBack,
                  progress progressCallback: @escaping ProgressCallBack) {

}

I am using it like this:

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     
        }
        
    }

Here is what converted code looks without progress reporting:

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

  //  return here
  }
}

You could use a technique similar to this:

https://developer.apple.com/documentation/foundation/urlsession/3767352-data

As you can see from the signature...

func data(for request: URLRequest, 
          delegate: URLSessionTaskDelegate? = nil) async throws 
              -> (Data, URLResponse)

...it is async, but it also takes a delegate object:

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

As you can see, that delegate receives callbacks for task progress. You can declare something similar, and thus feed that info from the delegate over to the main actor and the interface.

I took a while but I finally achieved this result, first you have to start the task setting a delegate:

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

In your delegate you subscribe to the progress update:

 public func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) {
    progressObservation = task.progress.observe(\.fractionCompleted) { progress, value in
        print("progress: ", progress.fractionCompleted)
    }
}

Don't forget that "progressObservation" needs to be a strong reference

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM