Notification center messages
Use Foundation’s notification center with Swift concurrency.
Overview
In Swift, the Notification type is nonisolated, even in cases where it’s posted on a known isolation. To provide specific isolation information and better support Swift concurrency, NotificationCenter defines two message types. A NotificationCenter.MainActorMessage binds to the main actor, whereas a NotificationCenter.AsyncMessage uses an arbitrary isolation. Frameworks extend these types to define distinct messages, typically corresponding to an existing Notification.Name, that declare instance properties for their values instead of using a userInfo dictionary. As a result, messages can conform to Sendable when they either don’t use properties or contain only sendable properties.
If your project only needs to support Swift, you can just use the Message types. For projects with both Objective-C and Swift code, define a Notification as well as a corresponding Message type.
Posting and observing messages
You can post a message with the post(_:subject:) method, passing a message instance and optionally providing a subject. To receive messages, add an observer with the addObserver(of:for:using:) method. The overloads of this method allow you to observe either messages from a single object or from any object of a given type. Observation ends when you discard the token returned from addObserver(of:for:using:) or after an explicit call to removeObserver(_:).
You can also receive messages as an AsyncSequence with the messages(of:for:bufferSize:) methods.
Several flavors of addObserver(of:for:using:) and messages(of:for:bufferSize:) take a NotificationCenter.MessageIdentifier, which frameworks may implement to provide a typed, ergonomic experience at the call point for convenience, as described in SE-0299.
Using messages with the SDK
Many system frameworks — including Foundation, UIKit, and AppKit — adopt the NotificationCenter.MainActorMessage and NotificationCenter.AsyncMessage types to facilitate using their notifications in concurrency-safe Swift code. The following example shows how to observe Foundation’s TimeZone type for the systemTimeZoneDidChange message, which contains the property previousTimeZone.
/// Note: Store `token` in a property for as long as you intend to observe.
token = NotificationCenter.default.addObserver(of: TimeZone.self,
for: .systemTimeZoneDidChange)
{ message in
let identifier = message.previousTimeZone?.identifier ?? "(unknown)"
print("Time zone changed from \(identifier).")
}For use with existing notification code, NotificationCenter.MainActorMessage and NotificationCenter.AsyncMessage define helper methods that conforming types implement to convert a message to a corresponding notification and vice versa.
Topics
Declaring a message
Using message identifiers
Observing concurrency-safe notifications
addObserver(of:for:using:)addObserver(of:for:using:)addObserver(of:for:using:)addObserver(of:for:using:)addObserver(of:for:using:)addObserver(of:for:using:)removeObserver(_:)NotificationCenter.ObservationToken