Add NotificationCenter.smuggle for better ergonomics

This commit is contained in:
Sami Samhuri 2025-06-06 13:58:35 -07:00
parent 7057d23b72
commit 488a77205c
No known key found for this signature in database
3 changed files with 26 additions and 3 deletions

View file

@ -8,7 +8,7 @@ import Foundation
/// If you want to extract the contraband manually you can use the extension method ``Notification.smuggled()``.
///
/// When smuggling notifications you can use ``Notification.smuggle(:object:)`` to build up a notification with the correct
/// user info automatically.
/// user info automatically, or use ``NotificationCenter.smuggle(_:)`` as a convenience method that posts the notification directly.
public protocol Smuggled {}
public extension Smuggled {

View file

@ -39,6 +39,13 @@ public extension Notification {
// MARK: -
public extension NotificationCenter {
/// Posts a notification that smuggles the given `Smuggled` value.
///
/// - Parameter contraband: The `Smuggled` value to send.
func smuggle<Contraband: Smuggled>(_ contraband: Contraband) {
post(.smuggle(contraband))
}
/// Returns an `AsyncSequence` of notifications of a specific `Smuggled` type.
///
/// Each element of the sequence is a `Smuggled` value.

View file

@ -42,6 +42,22 @@ struct SmugglingTests {
// MARK: NotificationCenter extensions
@Test(.timeLimit(.minutes(1)))
@MainActor func notificationCenterSmuggle() async {
let center = NotificationCenter()
let task = Task {
for await contraband in center.notifications(for: HitchhikersNotification.self) {
#expect(contraband.answer == 42)
return
}
}
await Task.yield()
let contraband = HitchhikersNotification(answer: 42)
center.smuggle(contraband)
await task.value
}
// It's important that the tests and the notification-observing tasks are not on the same actor,
// so we make the tests @MainActor and observe notifications on another actor. Otherwise it's
// a deadlock.
@ -60,7 +76,7 @@ struct SmugglingTests {
await Task.yield()
let contraband = HitchhikersNotification(answer: 42)
center.post(.smuggle(contraband))
center.smuggle(contraband)
while !received { await Task.yield() }
}
@ -101,7 +117,7 @@ struct SmugglingTests {
await Task.yield()
let contraband = HitchhikersNotification(answer: 42)
center.post(.smuggle(contraband))
center.smuggle(contraband)
while !received { await Task.yield() }
}