Last active
May 20, 2023 02:02
-
-
Save inamiy/18585ead2df825e2c00c5abb6967fca0 to your computer and use it in GitHub Desktop.
`@propertyWrapper` + `@MainActor var wrappedValue` which propagates `@MainActor` context to the encapsulating type. https://twitter.com/inamiy/status/1659530309501853696
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@MainActor | |
class ViewModel: ObservableObject {} | |
@propertyWrapper | |
struct Wrapper<T> { | |
var wrappedValue: T | |
} | |
@propertyWrapper | |
struct MainWrapper<T> { | |
@MainActor var wrappedValue: T | |
} | |
//---------------------------------------- | |
struct Foo1 { | |
var viewModel: ViewModel = ViewModel() // ERROR: Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context | |
} | |
struct Foo2 { | |
@StateObject | |
var viewModel: ViewModel = ViewModel() // Compile OK | |
} | |
struct Foo3 { | |
@Wrapper | |
var viewModel: ViewModel = ViewModel() // ERROR: Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context | |
} | |
struct Foo4 { | |
@MainWrapper | |
var viewModel: ViewModel = ViewModel() // Compile OK | |
} | |
struct Foo5 { | |
@MainWrapper | |
var viewModel: ViewModel = ViewModel() // Compile OK | |
// Compile OK, even though it looks same as Foo1, | |
// because `Foo5.init` will automatically gain `@MainActor` by `@MainWrapper`, | |
// and `MainWrapper.init` will automatically gain `@MainActor` by `@MainActor var wrappedValue`. | |
var viewModel2: ViewModel = ViewModel() | |
} | |
// NOTE: Requires `@MainActor`, although there is no `@MainActor Foo5` or `@MainActor init`. | |
func testFoo5() { | |
_ = Foo5() // ERROR: Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context | |
} |
swift-evolution/0316-global-actors.md at main · apple/swift-evolution · GitHub
A struct or class containing a wrapped instance property with a global actor-qualified wrappedValue infers actor isolation from that property wrapper:
@propertyWrapper struct UIUpdating<Wrapped> { @MainActor var wrappedValue: Wrapped } struct CounterView { // infers @MainActor from use of @UIUpdating @UIUpdating var intValue: Int = 0 }
Another interesting fact when having multiple @globalActor
-ed @propertyWrapper
s: https://twitter.com/kntkymt/status/1659595057929031680
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
With above given, we can explain why the following code causes errors where error messages are different: