Search code examples
swiftswift-concurrency

MainActor warning with Coordinator Pattern


I have a main coordinator to start my application.

protocol Coordinator: AnyObject {
    func start()
}

class MMMainCoordinator: Coordinator {
    
    let navigationController: UINavigationController
    let letterStore = MockData.letterStore
    var rootVC: UIViewController!
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    func start() {
        let viewModel = MMHomeViewModel(letterStore: letterStore)
        viewModel.mainCoordinator = self
        let rootVC = MMHomeViewController(viewModel: viewModel)
        self.rootVC = rootVC
        navigationController.pushViewController(rootVC, animated: false)
    }
}

After adding @MainActor to this class I get a warning for the function start()

Main actor-isolated instance method 'start()' cannot be used to satisfy nonisolated protocol requirement.

Xcode also shows the fix.

Add 'nonisolated' to 'start()' to make this instance method not isolated to the actor.

What is this warning about?


Solution

  • The problem is that your protocol defines a requirement (the start function) that is not constrained to any particular context (it's noniosolated) but then you are trying to satisfy that requirement with a function that is isolated (namely the start function that is a method of MMMainCoordinator).

    The compiler is suggesting that you mark the function as nonisolated everywhere to make it explicit that it's not tied to a particular context.

    You can either do that, or you can indicate that the requirements of the protocol itself can only be satisfied by code that is isolated to the main actor:

    @MainActor
    protocol Coordinator: AnyObject {
        func start()
    }
    
    @MainActor
    class MMMainCoordinator: Coordinator {
    
        func start() {
        }
    }