AlamoFire downloadProgress completion handler to async/await

1.7k Views Asked by At

I have created a download handler which uses the downloadProgress and response completion handlers, but I want to convert this to Swift 5.5's new async/await syntax since AlamoFire released a version which supports swift concurrency.

Here's my current code using completion handlers

func startDownload() {
    let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
    
    AF.download("https://speed.hetzner.de/1GB.bin", to: destination)
        .downloadProgress { progress in
            print(progress.fractionCompleted)
        }
        .response { response in
            print(response)
        }
}

Here's my attempt to convert to async/await syntax, but I am not sure how to implement downloadProgress

func startDownload() async {
    let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
    
    let downloadTask = AF.download("https://speed.hetzner.de/1GB.bin", to: destination).serializingDownloadedFileURL()
    
    do {
        let fileUrl = try await downloadTask.value
        
        print(fileUrl)
    } catch {
        print("Download error! \(error.localizedDescription)")
    }
}

I would appreciate any help.

1

There are 1 best solutions below

2
Jon Shier On BEST ANSWER

You can continue using your existing downloadProgress handler, there's no requirement to switch to the new syntax, especially since doing so will look very similar.

let task = AF.download("https://speed.hetzner.de/1GB.bin", to: destination)
  .downloadProgress { progress in
    print(progress.fractionCompleted)
  }
  .serializingDownloadedFileURL()

Or you can get the Progress stream and await the values in a separate Task.

let request = AF.download("https://speed.hetzner.de/1GB.bin", to: destination)

Task {
  for await progress in request.downloadProgress() {
    print(progress)
  }
}

let task = request.serializingDownloadedFileURL()

Also, you shouldn't use progress.fractionCompleted unless the process.totalUnitCount > 0, otherwise you won't get a reasonable value when the server doesn't return a Content-Length header that the progress can use for the totalUnitCount.