skip to Main Content

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search