How to Create Callback-like Behavior Using AsyncStream in Swift
No more relying on closures.
--
This article is originally published at swiftsenpai.com
Without a doubt, Swift Concurrency has revolutionized the way we handle asynchronous code in Swift. One powerful component of it is AsyncStream
, a specialized form of AsyncSequence
that is well-suited to achieve callback- or delegate-like behavior using the async/await syntax.
Prior to Swift Concurrency, developers had to rely on closures to trigger callbacks and inform callers about certain events during asynchronous operations. However, with the introduction of AsyncStream
, this closure-based approach can now be replaced with a more intuitive and straightforward async/await syntax.
In this article, let’s explore a simple yet illustrative example of how AsyncStream
can be utilized to track the progress of a download operation. By the end of this reading, you will have a good understanding of how AsyncStream
works and start using it in your own projects.
So, without further ado, let’s get started.
The Sample App
In order to showcase the power of AsyncStream
, let’s create a sample app that will simulate a download operation and display the download progress using a progress bar.
To emulate the waiting period typically associated with a file download, I have created a File
struct with a performDownload()
method that will sleep for a random amount of duration.
struct File {
let name: String
func performDownload() async {
// Sleep for a random amount of time to emulate the wait required to download a file
let downloadTime = Double.random(in: 0.03...0.5)
try? await Task.sleep(for: .seconds(downloadTime))
}
}
In a real-life situation, this performDownload()
method will most likely consist of code that connects to a server and waits for its response.
With that explanation out of the way, let’s delve into the interesting part.
Creating an AsyncStream
First of all, let’s create a downloader class (FileDownloader
) that accept an array of File
…