I have a Mac app that needs to perform an action when the Mac sleeps. To do this, I'm using this "modern" approach to listen for the notification:
@MainActor
final class AppController: NSObject, ObservableObject
{
var sleepTask: Task<Void, Never>? = nil
override init()
{
sleepTask = Task { [weak self] in
for await _ in NSWorkspace.shared.notificationCenter.notifications(named: NSWorkspace.willSleepNotification)
{
self?.doSomething()
}
}
}
}
Xcode 15 beta 8 has introduced a new warning on the for/await
call:
Non-sendable type 'Notification?' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary
1. Generic enum 'Optional' does not conform to the 'Sendable' protocol (Swift.Optional)
But I'm not using the notification object at all; it's not crossing the actor boundary.
How can I silence this warning? (Other than forcing Optional
to conform to @unchecked Sendable
).
You said:
How can I silence this warning? (Other than forcing
Optional
to conform to@unchecked Sendable
).
You can:
You can declare Notification
to be Sendable
. E.g.,
extension Notification: @unchecked Sendable { }
This silences the warning, but generally is inadvisable. If a type is not Sendable
, one should not bypass this and retroactively add Sendable
conformance, effectively making promises that you might not be able to keep.
You can also change your sequence to yield something other than a Notification
:
sleepTask = Task { [weak self] in
let sequence = NSWorkspace
.shared
.notificationCenter
.notifications(named: NSWorkspace.willSleepNotification)
.map { _ in () }
for await _ in sequence {
self?.doSomething()
}
}