NotificationCenter.MainActorMessage
A protocol for creating types that you can post to a notification center and bind to the main actor.
Declaration
protocol MainActorMessage : SendableMetatypeOverview
You post types conforming to MainActorMessage to a notification center using post(_:subject:) and observe them with addObserver(of:for:using:). The notification center delivers MainActorMessage types synchronously when posted.
For types that post on an arbitrary isolation, use NotificationCenter.AsyncMessage.
Each MainActorMessage is associated with a specific Subject type.
For example, a MainActorMessage associated with the type Event could use the following declaration:
struct EventDidStart: NotificationCenter.MainActorMessage {
typealias Subject = Event
}MainActorMessage 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
MainActorMessage 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 MainActor 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.MainActorMessage:
struct EventDidFinish: NotificationCenter.MainActorMessage {
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 MainActorMessage type receives information even if the poster used the Notification equivalent, and vice versa.