If I declare this protocol and model:
protocol SubScene: UIViewController {
func doSomething()
}
struct Model {
let subScene: SubScene
func longCalculation() async {
// Some long-running operation...
await subScene.doSomething()
}
}
class MyVC: UIViewController, SubScene {
func doSomething() {
performSegue(withIdentifier: "segue", sender: nil)
}
}
let myVC = MyVC()
let model = Model(subScene: myVC)
Task.detached {
await model.longCalculation()
}
I've declared a protocol that is restricted to UIViewController, and a model which calls the protocol's doSomething() method from an async context. Since UIViewController is a MainActor, my expectation is that doSomething() should get called on the main thread.
However, it does not. In fact the await keyword results in a warning from Swift that it is not calling an async method. And empirical testing shows that doSomething() will often end up being called on some other thread.
I can fix that by annotating doSomething() as a MainActor:
protocol SubScene: UIViewController {
@MainActor func doSomething()
}
This gets rid of the Swift warning and also results in doSomething() getting called on the correct thread.
Is this the correct approach, or is there another way that I could be doing this that avoids having to sprinkle all of my protocol methods with @MainActor?
CodePudding user response:
You could, alternatively, mark the entire protocol as @MainActor, e.g.,
@MainActor protocol SubScene: AnyObject {
func doSomething()
}
That avoids the need to declare each conforming method individually.
