Swift - Can I achieve mutual generics reference to classes?

131 Views Asked by At

I want to have two classes that are bound. This means, both classes know about each other methods.

BaseController <> BaseView

Those classes are used to declare subclasses, for example

LoginController <> LoginView.

BaseController has a strong reference to its view of kind <T : BaseView>, BaseView should have a weak reference to its controller of kind <T: BaseController>

I have managed to have a generic to BaseView:

  class BaseController <T: BaseScreen>

so that I do:

 class LoginController : BaseController<LoginView> 

that works and the controller has direct access (visibility) to the view functions and I don't need to cast every time.

However I cannot do the same on the View, because if I do

 class BaseView <T : BaseController>

Then the compiler forces me to do

class BaseView <T : BaseController <BaseScreen>> 

Which results in a recursion error.

Is there a way I can do that cross reference using generics? Right now I'm sticking with the view simply casting to the Controller in case it is needed.

1

There are 1 best solutions below

2
Palle On

You can use protocols and associated types instead of base classes (and implement the methods of the base type in a protocol extension):

protocol ControllerProtocol: class {
    associatedtype View: ViewProtocol
    var view: View { get }
}
protocol ViewProtocol: class {
    associatedtype Controller: ControllerProtocol
    weak var controller: Controller { get }
}

A class implementing one of the protocols has to specify a typealias to the desired related class:

class LoginController: ControllerProtocol {
    typealias View = LoginView
    var view: LoginView
    ...
}

class LoginView: ViewProtocol {
    typealias Controller = LoginController
    weak var controller: LoginController
    ...
}