When trying to use a Task
inside the init
method of a class derived from NSWindowController
, I have to explicitly annotate the initializer with @MainActor
otherwise the compiler will complain if I attempt to call another property that is designated on the main actor.
However, I don't have to explicitly do this in a function on the class. Only the initializer. I assume this has to do with how @MainActor
is specified on AppKit classes but I couldn't find any authoritative posts on that.
Consider:
import AppKit
final class WindowController: NSWindowController {
let label = NSTextField()
// This annotation is required otherwise the following error is reported:
// Property 'stringValue' isolated to global actor 'MainActor' can not
// be mutated from a non-isolated context.
@MainActor
init() {
super.init(window: nil)
Task {
label.stringValue = "Hello World"
}
}
// However, no such annotation is required here. Why is that?
func updateLabel() {
Task {
label.stringValue = "Hello World"
}
}
}
Note that annotating the entire class with @MainActor
does not seem to make a difference.
Are there any special rules for which async context I'm in from within a classes init
method. What about for AppKit
instances in particular?
SE-0316 briefly touches upon this under the section Using global actors on functions and data but in that example @MainActor
is actually applied to every property and function.