Subclasses inherit the @MainActor
attribute which ensures synchronised access on the main thread to all its stored. But what if I don't want this "exclusive access" functionality. Take the following example:
class GameScene: SKScene {
var imagesToUpload = ["cat", "mouse", "dog"]
var lastUploaded = ""
func uploadAllImages() async {
await withTaskGroup(of: Void.self) { group in
for name in imagesToUpload {
group.addTask {
await self.uploadImage(of: name)
self.lastUploaded = name // << Error: Main actor-isolated property 'lastUploaded' can not be mutated from a Sendable closure
}
}
}
}
func uploadImage(of: String) async {
try! await Task.sleep(for: .seconds(1))
}
}
SKScene
inherits from UIResponder
which is declared using @MainActor
. From what I understand of this error, a Sendable closure is a closure which captures values that are all Sendable, i.e., safe to access from multiple threads. But in this case, I don't care about multiple threads changing the value of this variable at the same time. To fix this issue in my testing, I had to do this:
group.addTask { @MainActor in
await self.uploadImage(of: name)
self.lastUploaded = name
}
But here is my worry about doing this: If @MainActor
closures run on the Main Thread, won't that freeze up the UI due to the upload? In addition to that, it also defeats the purpose of using a TaskGroup as all of these uploads will get queued up on the Main Thread, which will basically make them happen sequentially due to the "await" keyword.
So my question is, how do I asynchronously modify properties that inherit the @MainActor
attribute? Is there a way to turn this exclusive/synchronised access off?
Edit:
I only want to know if it's possible to remove the inherited @MainActor
declaration on my property. Perhaps a way to declare it as nonisolated
.