Applying a global actor, like @MainActor
, to a type declaration adds an implicit @MainActor
in that type's properties and methods.
This means that your example is equivalent to:
class Test: Sequence {
@MainActor private var contents: [Int] = []
@MainActor
func makeIterator() -> Array<Int>.Iterator {
contents.makeIterator()
}
}
This is an issue because Sequence
has a makeIterator
requirement that is not isolated to a specific global actor. If this was the case you wouldn't be able to use a for-loop on an Array
in a background thread. So, to opt-out of the implicit isolation, you can write:
@MainActor class Test: Sequence {
private var contents: [Int] = []
nonisolated func makeIterator() -> Array<Int>.Iterator {
// You can't use the isolated property 'contents'
// here, because it's isolated
}
}
Perhaps you intend to make Test
conform to a Sequence
-like protocol whose requirements are isolated to @MainActor
. Unfortunately, a similar feature has only been proposed as a future direction.
If you are still confused, it's worth taking a step back and thinking about what you really want to achieve. Actor isolation offers a way to safely mutate data shared across threads. Thus, no isolation implies either a lack of mutation (hence the ability to mark let
properties nonisolated
) or a synchronization mechanism other than actors.