In the body of observeAppStatus
we end up with:
for await _ in await NotificationCenter.default.notifications(for: UIApplication.willResignActiveNotification) {
try? await say("\(username) went away", isSystemMessage: true)
}
You can see there are two awaits
– seemingly the first for awaiting the elements in the AsyncStream
, and the second for awaiting the result of the notifications(for:)
function call. The thing is that notifications(for:)
is not marked async
, but the compiler still requires the second await
to compile. This is not the case if we use a nearly-identical example I’ll call stupidGarbage
:
extension NotificationCenter {
// Method from book, not marked async
func notifications(for name: Notification.Name) -> AsyncStream<Notification> {
return AsyncStream<Notification> { continuation in
NotificationCenter.default.addObserver(forName: name, object: nil, queue: nil) { note in
continuation.yield(note)
}
}
}
// Nearly identical method, also not marked async
func stupidGarbage() -> AsyncStream<String> {
return AsyncStream<String> { continuation in
continuation.finish()
}
}
}
In this case, awaiting the elements doesn’t require the second await:
func observeAppStatus() async {
// Removing the second await causes a compilation error
for await _ in await NotificationCenter.default.notifications(for: UIApplication.willResignActiveNotification) {
try? await say("\(username) went away", isSystemMessage: true)
}
// One await works fine here though
for await thing in NotificationCenter.default.stupidGarbage() {
try? await say(thing)
}
}
Is there some implicit thing here that I’m missing? Maybe a compiler error?