Get immediate access to this and 4,000+ other videos and books.
Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and
4,000+ professional videos in a single subscription, it's simply the best investment you can make in
your development career.
When downloading images or large files over the network, the user oftentimes will want to know the progress of the total download. If using the closure-based task downloads on URLSession, you have delegate methods for this. If you wanna use the asynchronous functions of URLSession, then switching over from the data or download methods over to the bytes methods is what you need. The delegate method is called URLSession DownloadTask, didWriteData. This passes in three important values: The bytes written, the total bytes written, and the total bytes expected to write. When a file is saved, it's downloaded all the time. Each time this method is called, the bytes written is the number of bytes that were saved to disk. The total bytes written is the total bytes that have been saved to disk, and the total bytes expected to write is the actual size of the file. When using the asynchronous APIs, you retrieve the contents of a URL or URL request and get back an asynchronous sequence of bytes for you to store in memory or on disk. We'll be working with the asynchronous APIs in this episode. So let's get started. Let's add some better error handling to the app. Start by opening the starter project for this episode. Open SongDetailView dot Swift and add a property to keep track of the download progress. And with this property, update your Progress View. To comply with Progress View's expectation for value, you'll also keep the property from zero to one, to represent zero to a hundred percent. Open Song Downloader dot swift. In here, you're going to add a new method that downloads a song using URLSession's bytes method. Add the following code. This method works similar to DownloadSong by taking a download URL but it also has a progress property that's a float binding for you to keep track of the download progress. Similarly, this method is async and can throw errors. Switch back to SongDetailView dot Swift real quick and replace the call to Download Song with the following. You call the new method on Song Downloader and pass Download Progress as the binding that will be used to keep track of the download. Back in Song Downloader, it's time to implement the new Download Song bytes method. Start by adding this code. This is very similar to the methods you've been using, except the downloads bytes that are returned as an asynchronous sequence. Moving on, add the following. This code will help you check the response's expected content length, which you then use to create a new data object with a reserved capacity of the expected size of the bytes to download. Because the ?? returned from the asynchronous bytes call contains the sequence of bytes with your data, iterate through these bytes with the following. Note how you use try await to loop through this async sequence. In the For loop, you want to append the bytes that are downloaded to the data object you created earlier. And to actually see the progress of the download, you want to update the progress parameter. Note that because the progress parameter is the binding, you wanna update its wrapped value with the actual floating point number from zero to one that corresponds to your download progress. Build and run the app. Tap the Download button and check out the results. Yay. You see the progress view in action, even though the actual bytes downloaded aren't being handled. So your button reverts back to saying Download. You may have also noticed that the download might have felt incredibly slow when compared to the code you were previously using. This is because updating the progress value on every iteration of the loop isn't the most optimal thing to do. So time to tweak the code a little bit to improve its performance. Replace the line where you set the progress parameter with the following. This stores the current progress of the download. Then add the following. What this does is set the progress parameter only if the current progress is different. Otherwise, the loop continues. Build and run the app, and give things a try one more time. That was much, much faster. It might be so fast that you barely even got a chance to enjoy your progress view. Don't worry. I'll show you how to test different network connections in a couple of episodes. But for now it's time to actually store these downloaded bytes into a file on disk. Add this code at the bottom of your For loop. As before, you are working with File Manager to acquire the URL for the app's document directory. If something goes wrong in the process then you throw an error. Time to construct the URL for where to save the song. And then write the actual bytes to a file on disk. Excellent. This should look very familiar to what you wrote in the Download Song method. Finally, and in order for your app to know that the song was downloaded successfully, you want to update the download location property. Build and run your app, tap the Download button, and check out the results. Excellent. Everything is working as expected and just as it was before, but now you actually see the download progress in your UI. Great work. Not only are you making the app a lot better and more functional for users, but you're also learning more concepts and functionality that URLSession provides. In the next episode, I'll show you how you can group multiple requests together, so that you can treat the song and artwork downloads as a single operation, even if they're performed individually and concurrently. See ya there.
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.