Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the download progress with the new try await URLSession.shared.download(...)

Apple just introduced async/await and a bunch of Foundation functions that use them. I'm downloading a file using the new async/await pattern, but i cannot seem to get the download progress.

(downloadedURL, response) = try await URLSession.shared.download(for: dataRequest, delegate: self) as (URL, URLResponse)

As you can see, there is a delegate, and i have tried conforming my class to the URLSessionDownloadDelegate and implementing the urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:) function, but it never gets called.

I also tried creating a new URLSession and setting it's delegate to the same class, in hopes that URLSession would call this function instead, but it never gets called and the file still happily downloads. But i need the progress, how do i get it please?

like image 728
Maciej Swic Avatar asked Nov 06 '22 01:11

Maciej Swic


1 Answers

You can use URLSession.shared.bytes(from: imageURL) and for await in to loop over.

URLSession.shared.bytes returns (URLSession.AsyncBytes, URLResponse). AsyncBytes is async a sequence that can be looped over using for await in.

func fetchImageInProgress(imageURL: URL) async -> UIImage? {
    do {
        let (asyncBytes, urlResponse) = try await URLSession.shared.bytes(from: imageURL)
        let length = (urlResponse.expectedContentLength)
        var data = Data()
        data.reserveCapacity(Int(length))

        for try await byte in asyncBytes {
            data.append(byte)
            let progress = Double(data.count) / Double(length)
            print(progress)
        }
        return UIImage(data: data)
    } catch {
        return nil
    }
}

It shows like below progressive fetching image.

enter image description here

like image 131
Won Avatar answered Nov 14 '22 11:11

Won