The Xcode 13.4RC release notes contain the following improvement:
- Closures that are guaranteed to run on the main actor are now permitted to reference local variables from their enclosing scopes that are also running on the main actor.
@MainActor class MyController: UIViewController { var isExcited: Bool = false func doSomething() { var title = "Hello" Task { @MainActor in if isExcited { // okay, accessing main actor-isolated stored property title += "!" // okay, accessing main actor-isolated local variable } } } }
(90665432)
That this change seems limited to the MainActor
seems odd to me given the original language of SE-0304.
Context inheritance
Unstructured tasks created with the
Task
initializer inherit important metadata information from the context in which it is created, including priority, task-local values, and actor isolation.If called from the context of an existing task:
...
- if executed within the scope of a specific actor function:
- inherit the actor's execution context and run the task on its executor, rather than the global concurrent one,
- the closure passed to
Task {}
becomes actor-isolated to that actor, allowing access to the actor-isolated state, including mutable properties and non-sendable values.
Perhaps I've misunderstood this section this entire time, but I originally thought it meant Task {}
inherited the actor context it was created in, including global actors. But I'm not sure. Does this only apply to calls from within actual actor
types? Or does it only apply to Task
s within Task
s within actor
s?
In short, can someone clarify the actual rules around Task
actor inheritance and explain how the change in Xcode 13.4 violates it for MainActor
?