Hello :)
Lately, I've been wondering about Tasks and which thread the execute on using @MainActor, as I understand they execute on whatever context they are created in. For example, in this very common scenario:
@MainActor
class ViewModel: ObservableObject {
@Published var name: String?
init() {
fetchData()
}
private func fetchData() {
Task {
print("Thread: ", Thread.current)
name = await request()
}
}
private func request() async -> String {
// Network Request
print("Thread: ", Thread.current)
return "Name"
}
}
In this scenario, we have annoteded the full class to use @MainActor, so the Tasks are also running on this thread.
In the console I can confirm this too with the print statements.
But wouldn't this be blocking the main thread if it was doing real fetching?
I know Task don't have to suspend themselves, it's up to the system. But isn't this an issue? Should we explicitly create background threads or should we not annoate the full class as a @MainActor as shown below:
class ViewModel: ObservableObject {
@Published var name: String?
init() {
fetchData()
}
private func fetchData() {
Task {
print("Thread: ", Thread.current)
let name = await request()
await MainActor.run {
print("Thread: ", Thread.current)
self.name = name
}
}
}
private func request() async -> String {
print("Thread: ", Thread.current)
return "Niclas"
}
}
In this scenario, the Tasks are created on a background thread as I can see in the console and instead I'm using the MainActor.run
to update my @Published
property on the main queue
.
Let me know in the comments :)