Is there any difference between:
Task { await MainActor.run { ... } }
and
Task { @MainActor in ... }
Is there any difference between:
Task { await MainActor.run { ... } }
and
Task { @MainActor in ... }
One difference is that one takes a synchronous closure whereas the other uses an async
closure. Specifically, run
takes a synchronous closure (i.e., the body
is not async
):
public static func run<T>(resultType: T.Type = T.self, body: @MainActor @Sendable () throws -> T) async rethrows -> T where T : Sendable
This is ideally suited for the scenario where you are on some other actor, but want to run a series of three methods, all of which are isolated to the main actor, but want to do it with a single context switch, not three.
But, in Task.init
, the operation
is async
, which makes it a slightly more flexible mechanism:
public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async -> Success)
So, to illustrate the difference, consider:
Task { @MainActor in
statusText = "Fetching"
await viewModel.fetchData()
statusText = "Done"
}
But you cannot await
within MainActor.run
:
Task {
await MainActor.run { // Cannot pass function of type '@Sendable () async -> ()' to parameter expecting synchronous function type
statusText = "Fetching"
await viewModel.fetchData()
statusText = "Done"
}
}
You would have to insert yet another Task
inside. (!)
Task {
await MainActor.run {
Task {
statusText = "Fetching"
await viewModel.fetchData()
statusText = "Done"
}
}
}
I actually use both patterns sparingly, but this is one difference between them.
© 2022 - 2025 — McMap. All rights reserved.