NotificationCenter.AsyncMessage
A protocol for creating types that you can post to a notification center, which posts them to an arbitrary isolation.
Declaration
protocol AsyncMessage : SendableOverview
You post types conforming to AsyncMessage to a notification center using post(_:subject:) and observe them with addObserver(of:for:using:).
The notification center delivers AsyncMessage types asynchronously when posted. Asynchronous delivery isn’t suitable for messages with time-critical deliveries, such as a message that must have its observers called before a certain action takes place.
For types that post on the main actor, use NotificationCenter.MainActorMessage.
Each AsyncMessage is associated with a specific Subject type.
For example, an AsyncMessage associated with the type Event could use the following declaration:
struct EventDidStart: NotificationCenter.AsyncMessage {
typealias Subject = Event
}AsyncMessage can use an optional NotificationCenter.MessageIdentifier type for context-aware observer registration:
extension NotificationCenter.MessageIdentifier where Self == NotificationCenter.BaseMessageIdentifier<EventDidStart> {
static var didStart: Self { .init() }
}With this identifier, observers can receive information about a specific instance by registering for this message with a NotificationCenter:
let observerToken = NotificationCenter.default.addObserver(of: importantEvent, for: .didStart)Or an observer can receive information about any instance with:
let observerToken = NotificationCenter.default.addObserver(of: Event.self, for: .didStart)The notification center ties observation the lifetime of the returned NotificationCenter.ObservationToken and automatically de-registers the observer if the token goes out of scope. You can also remove observation explicitly:
NotificationCenter.default.removeObserver(observerToken)Notification Interoperability
AsyncMessage includes optional interoperability with Notification, enabling posters and observers of both types to pass information.
It does this by offering a makeMessage(_:) method that collects values from a Notification‘s userInfo and populates properties on a new message. In the other direction, a makeNotification(_:) method collects the message’s defined properties and loads them into a new notification’s userInfo dictionary.
For example, if there exists a Notification posted on an arbitrary isolation identified by the Notification.Name "eventDidFinish" with a userInfo dictionary containing the key "duration" as an NSNumber, an app could post and observe the notification with the following NotificationCenter.AsyncMessage:
struct EventDidFinish: NotificationCenter.AsyncMessage {
typealias Subject = Event
static var name: Notification.Name { Notification.Name("eventDidFinish") }
var duration: Int
static func makeNotification(_ message: Self) -> Notification {
return Notification(name: Self.name, userInfo: ["duration": NSNumber(message.duration)])
}
static func makeMessage(_ notification: Notification) -> Self? {
guard let userInfo = notification.userInfo,
let duration = userInfo["duration"] as? Int
else {
return nil
}
return Self(duration: duration)
}
}With this definition, an observer for this AsyncMessage type receives information even if the poster used the Notification equivalent, and vice versa.