GreatOm
September 16, 2024, 11:55am
1
I don't understand the reason of this error after switching to Xcode 16, Swift 6 language version.
My simplified code looks like this:
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
let windowInfo = WindowInfo()
func applicationDidFinishLaunching(_ aNotification: Notification) {
window = NSWindow( … ) // Create the window and set the content view.
Task { @MainActor in
NotificationCenter.default.addObserver(forName: NSWindow.didMoveNotification, object: nil, queue: nil) { [self] (notification) in windowInfo.windowFrame = window.frame }
NotificationCenter.default.addObserver(forName: NSWindow.didResizeNotification, object: nil, queue: nil) { [self] (notification) in windowInfo.windowFrame = window.frame }
}
}
}
I did already add a Task(…) to make sure to be on MainActor but following error remains:
Capture of 'self' with non-sendable type 'AppDelegate' in a `@Sendable` closure
Class 'AppDelegate' does not conform to the 'Sendable' protocol
Any clue how to solve this issue?
1 Like
mattie
September 16, 2024, 12:26pm
2
NSApplicationDelegate
does not automatically make your type MainActor
. I believe you can address this by removing the Task
and instead marking your type @MainActor
.
I also think this is quite annoying, especially since UIApplicationDelegate
does use @MainActor
. I've filed a bug about this previously: FB13883653.
1 Like
GreatOm
September 16, 2024, 12:54pm
3
Thanks for your reply.
I added the Task to get rid of Actor issues but a change to
@MainActor func applicationDidFinishLaunching(_ aNotification: Notification) {
…
NotificationCenter.default.addObserver(forName: NSWindow.didMoveNotification, object: nil, queue: nil) { [self] (notification) in windowInfo.windowFrame = window.frame }
NotificationCenter.default.addObserver(forName: NSWindow.didResizeNotification, object: nil, queue: nil) { [self] (notification) in windowInfo.windowFrame = window.frame }
}
gives still the errors
Capture of 'self' with non-sendable type 'AppDelegate' in a *@Sendable closure
Class 'AppDelegate' does not conform to the 'Sendable' protocol
for windowInfo and
Main actor-isolated property 'frame' can not be referenced from a Sendable closure
Property declared here (AppKit.NSWindow)
for window.frame .
Both window and windowInfo are declared in the AppDelegate class.
I guess a different way to declare is needed…
mattie
September 16, 2024, 1:02pm
4
Sorry, I wasn't clear!
If you look at the definition of applicationDidFinishLaunching
, you'll see that it is marked @MainActor
already. That is actually the problem. Your AppDelegate
type is not.
Try this:
@MainActor
class AppDelegate: NSObject, NSApplicationDelegate {
// ...
}
This exact problem isn't covered by the migration guide, but the concept is and a similar problem is presented. Might be worth checking out.
https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/commonproblems#Latent-Isolation
1 Like
GreatOm
September 16, 2024, 1:22pm
5
May thanks. I did a quick look at the provided link and it looks promising…
1 Like
GreatOm
September 25, 2024, 9:22am
6
Got it working in Swift 6 language mode.
I made following changes:
Added @MainActor :
@MainActor
class AppDelegate: NSObject, NSApplicationDelegate {
…
}
The notification code is now running in a Task:
NotificationCenter.default.addObserver(forName: NSWindow.didMoveNotification, object: nil, queue: .main) { [self] (notification) in
Task { @MainActor in
windowInfo.windowFrame = window.frame
}
}
Many thanks for your help which did lead me to a solution.
1 Like