Home > Net >  Async await not fire in the project, but works fine in Xcode playground
Async await not fire in the project, but works fine in Xcode playground

Time:06-14

The following code piece works in Xcode playground, but not working if I put into .onAppear/.task in a project.

Appreciate if anyone could help me on it.

let n = Notification.Name("event")
Task {
    for await value in NotificationCenter.default.notifications(named: n, object: nil) {
        if let str = value.object as? String {
            await asyncPrint(value: str)
        }
    }
}

NotificationCenter.default.post(name: n, object: "event1")
NotificationCenter.default.post(name: n, object: "event2")
NotificationCenter.default.post(name: n, object: "event3")

CodePudding user response:

Your notifications are going to be posted before the observation is added. There is no queue of previous notifications. If nothing is waiting on the notification, it is discarded.

The likely order for your code is:

  • Create n
  • post, post, post (no observers, so they're discarded)
  • Then the Task starts and begins waiting. No notifications ever show up.

This can work in a playground because playgrounds evaluate things in unusual orders, and may evaluate various lines more than once. It is extremely difficult to use playgrounds to explore async code because you don't know what order things will be evaluated in.

CodePudding user response:

If you create your notifications stream outside of the Task, and before you post, it eliminates this timing issue:

let n = Notification.Name("event")
let notifications = NotificationCenter.default.notifications(named: n, object: nil)

Task {
    for await notification in notifications {
        if let string = notification.object as? String {
            await asyncPrint(value: string)
        }
    }
}

NotificationCenter.default.post(name: n, object: "event1")
NotificationCenter.default.post(name: n, object: "event2")
NotificationCenter.default.post(name: n, object: "event3")
  • Related