swiftactorswift-concurrency

Swift: Silence "Non-Sendable Notification? cannot cross actor boundary" warning


Problem

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)

enter image description here

But I'm not using the notification object at all; it's not crossing the actor boundary.

Question:

How can I silence this warning? (Other than forcing Optional to conform to @unchecked Sendable).


Solution

  • You said:

    How can I silence this warning? (Other than forcing Optional to conform to @unchecked Sendable).

    You can:

    1. 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.

    2. 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()
          }
      }