Modern Concurrency: Beyond the Basics

Oct 20 2022 · Swift 5.5, iOS 15, Xcode 13.4

Part 1: AsyncStream & Continuations

04. Using AsyncStream for Notifications

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 03. Using AsyncStream to Count Down Next episode: 05. Using a Buffered AsyncStream

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.

Learn more Already a subscriber? Sign in.

Notes: 04. Using AsyncStream for Notifications

This video uses Xcode 14’s Task.sleep(until:clock:). If you use Xcode 13, replace this with Task.sleep(nanoseconds: 1_000_000_000).

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

Refresh your browser to make sure the course server is running or restart the server in Terminal. Continue with your project from the previous episode or open the starter project for this episode.

Adding an asynchronous stream to NotificationCenter

Chat users expect to see system messages when another user leaves the chat or returns. Your app can get this information from NotificationCenter, one of Apple’s built-in frameworks.

func notifications(for name: Notification.Name) -> AsyncStream<Notification> {
  AsyncStream<Notification> { continuation in

  }
}
NotificationCenter.default.addObserver(
  forName: name, 
  object: nil, 
  queue: nil
) { notification in
  continuation.yield(notification)
}
func observeAppStatus() async {

}
for await _ in await NotificationCenter.default
  .notifications(for: UIApplication.willResignActiveNotification) {
  
}

Notifying participants when a user leaves

Now, add code in the loop to post a system message when a user leaves the chat:

try? await say("\(username) went away", isSystemMessage: true)
let notifications = Task {
  await observeAppStatus()
}
defer {
  notifications.cancel()
}

Notifying participants when a user returns

In BlabberModel, jump to observeAppStatus(). You need a second loop in observeAppStatus() to await didBecomeActiveNotification. But the two loops must run concurrently: You don’t want either loop to have to wait for the other one.

🟩Task {🟥
  for await _ in await NotificationCenter.default
        .notifications(for: UIApplication.willResignActiveNotification) {
    try? await say("\(username) went away", isSystemMessage: true)
  }
🟩}
Task {
  for await _ in await NotificationCenter.default
        .notifications(for: UIApplication.🟩didBecomeActiveNotification🟥) {
    try? await say("\(username) 🟩came back🟥", isSystemMessage: true)
  }
}