2

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.

code24
  • 458
  • 1
  • 3
  • 14

1 Answers1

2

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.

Jon Shier
  • 12,200
  • 3
  • 35
  • 37
  • I'm currently using progress.fractionCompleted for a Progress Bar in my UI, what would be an alternative to fractionCompleted if it's unreliable at times? – code24 Dec 19 '21 at 15:16
  • 2
    To make your UI switch to an indeterminate progress indicator in those cases. – Jon Shier Dec 19 '21 at 22:13