Type-Safe NotificationCenter

Type-safe wrapper around NotificationCenter with AsyncStream support.

← Back
Language: swift | Tags: notifications type-safe async observer
struct TypedNotification<Payload> {
    let name: Notification.Name

    init(_ name: String) {
        self.name = Notification.Name(name)
    }
}

extension NotificationCenter {
    func post<Payload>(_ notification: TypedNotification<Payload>, payload: Payload) {
        post(name: notification.name, object: nil, userInfo: ["payload": payload])
    }

    func publisher<Payload>(for notification: TypedNotification<Payload>) -> AsyncStream<Payload> {
        AsyncStream { continuation in
            let observer = addObserver(
                forName: notification.name,
                object: nil,
                queue: nil
            ) { notification in
                if let payload = notification.userInfo?["payload"] as? Payload {
                    continuation.yield(payload)
                }
            }
            continuation.onTermination = { @Sendable _ in
                self.removeObserver(observer)
            }
        }
    }
}

// Usage:
// enum Notifications {
//     static let userLoggedIn = TypedNotification<User>("userLoggedIn")
// }
// NotificationCenter.default.post(.userLoggedIn, payload: user)
// for await user in NotificationCenter.default.publisher(for: .userLoggedIn) { }