ARTICLE AD BOX
Asked 4 days ago
Viewed 79 times
I’m migrating a NotificationManager class to Swift 6. This class is a small utility wrapper around NotificationCenterand has a method that lets users register a notification that will triggerunless the object is equal to a particular NSObjectvalue.
For example:
manager.registerObserver(for: name, forObject: nil, ignoreIfSentFrom: self) { // run this code _only_ if the sender wasn't self }The method looks like this:
private func registerObserver(_ name: NSNotification.Name, forObject object: AnyObject?, ignoreIfSentFrom ignoredObject: NSObject, block: @Sendable @MainActor @escaping (Notification) -> ()) { let newToken = NotificationCenter.default.addObserver(forName: name, object: object, queue: nil) { note in guard (note.object as AnyObject) !== ignoredObject else { return } Task { @MainActor in block(note) } } observerTokens.append(newToken) }I get two errors here that I can’t figure out how to resolve:
Capture of 'ignoredObject' with non-Sendable type 'NSObject?' in a '@Sendable' closure (on the guard line) Sending 'note' risks causing data races; this is an error in the Swift 6 language mode (for block(note))Is it still possible to implement this idea with Swift 6 strict concurrency? It looks like Notification is neither Sendablenor @MainActor and since I don’t own that type, I’m at a loss for how to make this work.
46k25 gold badges128 silver badges219 bronze badges
I would also consider simply returning the async sequence to let the caller decide how to consume it.
private func notifications( _ name: NSNotification.Name, ignoreIfSentFrom ignoredObject: NSObject ) -> some AsyncSequence<Notification, Never> { let ignoredObjectID = ObjectIdentifier(ignoredObject) return NotificationCenter.default.notifications(named: name, object: nil).filter { ($0.object as? NSObject).map(ObjectIdentifier.init) != ignoredObjectID } }This way you don't force the caller to provide a main actor isolated callback. The caller can decide where it wants to be isolated (if at all).
3 Comments
Thanks! I'd forgotten about ObjectIdentifier. That resolves the first warning. This function is in a large project, and there are over 100 callers of this - switching to the async sequence version would be a bigger migration - maybe something I can do once Swift 6 is done 😅.
2025-11-23T11:57:14.157Z+00:00
@Bill The second warning should be resolved too? Did the first code snippet (not talking about the version that returns the async sequence) still emit the second warning? You are no longer sending the notification because everything is within Task { @MainActor in ... } now.
2025-11-23T12:37:19.707Z+00:00
Explore related questions
See similar questions with these tags.


