The reason that it doesn't work
Assuming your code would work and we write additionally
class ExampleCoordinator2: Coordinator {}
val viewController = ViewController()
viewController.coordinator = ExampleCoordinator2()
The assignment to coordinator
cannot work since ExampleCoordinator2
is not a subclass of ExampleCoordinator
.
So, just considering the types the following code should work but the Swift compiler doesn't allow it (this might work in the future):
protocol Coordinatable {
var coordinator: Coordinator { get } // removing the `set`
}
class ViewController: UIViewController, Coordinatable {
var coordinator: ExampleCoordinator! // still an error
}
Possible solutions
Using var coordinator: Coordinator
in ViewController
class ViewController: UIViewController, Coordinatable {
var coordinator: Coordinator
init(coordinator: Coordinator) {
self.coordinator = coordinator
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Using only { get }
in Coordinatable
protocol Coordinatable {
var coordinator: Coordinator { get } // removing the `set`
}
class ViewController: UIViewController, Coordinatable {
// computed property
var coordinator: Coordinator {
// implicit return
exampleCoordinator
}
var exampleCoordinator: ExampleCoordinator!
}
Using an associatedtype
in Coordinatable
protocol Coordinatable {
associatedtype C: Coordinator
var coordinator: C { get set }
}
class ViewController: UIViewController, Coordinatable {
var coordinator: ExampleCoordinator
init(coordinator: ExampleCoordinator) {
self.coordinator = coordinator
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
This has however a big disadvantage that you cannot have a heterogenous array of type [Coordinatable]
since Coordinatable
has an associatedtype
. And still, you cannot assign a value of type ExampleCoordinator2
.
You can only write generic code over <C: Coordinatable>
. E.g.
func printCoordinators<C: Coordinatable>(coordinatables: [C]) {
coordinatables.forEach {
print($0.coordinator)
}
}