Leave a rating/review
Notes: 05. Using a Buffered AsyncStream
Use Xcode 13 for this exercise. Xcode 14 beta uses Swift 6, which doesn’t allow using countdown in the scheduledTRimer closure.
Your challenge is to rewrite countdown(to:) using the buffered push-based version of AsyncStream.
Use Timer instead of Task.sleep to wait 1 second between messages. The starter project already has code for a Timer.scheduledTimer that fires every second.
Inside the scheduledTimer closure, yield the correct message when countdown is 3, 2, 1 and 0. Remember to decrement countdown after yielding 3, 2 and 1.
When countdown is 0, return the user’s message, invalidate the timer and finish the continuation.
Welcome back! Hopefully you had success with this task. Here’s how I did it.
In BlabberModel, countdown(to:) already has starter code to create a Timer that fires each second, instead of the pull-based AsyncStream code you wrote in episode 3:
let counter = AsyncStream<String> { continuation in
var countdown = 3
Timer.scheduledTimer(
withTimeInterval: 1.0,
repeats: true
) { timer in
}
}
Inside the timer closure, I first handled the countdown digits:
continuation.yield("\(countdown) ...")
countdown -= 1
On every timer tick, I called yield(_:) on the continuation to produce the countdown value, then decreased countdown.
Next, I needed to add code for when countdown reaches 0.
I did this before continuation.yield...
) { timer in
🟩guard countdown > 0 else {
timer.invalidate()
continuation.yield("🎉 " + message)
continuation.finish()
return
}
🟥continuation.yield("\(countdown) ...")
countdown -= 1
}
When countdown reaches 0: I stop the timer, yield the user’s message, and call continuation.finish() to complete the sequence.
Actually, there’s a shortcut to produce the last value and complete the sequence at the same time:
continuation.yield(with: .success("🎉 " + message))
To show it works:
The next episode is about unit testing.