-
-
Save siracusa/137e3fae8a384ac4bda8c56524826d6b to your computer and use it in GitHub Desktop.
NSWorkspace.shared.notificationCenter.addObserver( | |
forName: NSWorkspace.didLaunchApplicationNotification, | |
object: nil, queue: nil, using: { [weak self] notification in | |
self?.doStuff() | |
}) |
Oh well actually yes, you can achieve something similar in Swift:
extension NotificationCenter {
@MainActor
public func addMainActorObserver(
forName name: Notification.Name,
object obj: Any? = nil,
block: @escaping @MainActor (Notification) -> Void
) -> any NSObjectProtocol {
// this let's you lie to the compiler!
let sendableBlock = unsafeBitCast(block, to: (@Sendable (Notification) -> Void).self)
return self.addObserver(forName: name, object: obj, queue: .main, using: sendableBlock)
}
}
I'm not sure exactly what's up with the NS_SWIFT_UI_ACTOR
. I haven't looked into the clang annotations deeply but they are definitely supposed to work. Please file a bug if something isn't working as it should!
Perfect, thanks for the bitcast hack! And I'll look into the NS_SWIFT_UI_ACTOR
issue and file a bug if it's busted.
Also for anybody reading along: I think I decided I don't want/need the addMainActorObserver
to be @MainActor
. It's likely I'll only ever call it from the main thread, but because the method guarantees delivery on the main thread, it can be safely called from anywhere, I think.
I think this is correct! But, I also do want to point out that this version makes it possible to pass data unsafely across threads by way of the Notification
object. I don't think that's likely though.
Oh, right. That's a good point. Maybe I should leave it @MainActor
after all.
I think I got something working. I implemented an ObjC helper:
But for whatever reason the
NS_SWIFT_UI_ACTOR
wasn't coming through to the Swift side? I'll try to figure out a fix for that. But in the meantime, wrapping the ObjC helper above with a Swift-facing call that just calls through to it:Seems to work!