Использование связанного с протоколом типа в общих функциях - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь написать простой шаблон MVP, который будет следовать в моем приложении, поэтому я написал два протокола для определения View Controller и Presenters:

protocol PresenterType: class {
    associatedtype ViewController: ViewControllerType

    var viewController: ViewController? { get set }

    func bind(viewController: ViewController?)
}

protocol ViewControllerType: class {
    associatedtype Presenter: PresenterType

    var presenter: Presenter { get }

    init(presenter: Presenter)
}

После того, как они были определены, я начал писать некоторыеRootViewController и RootViewPresenter.Последний выглядит следующим образом:

protocol RootViewControllerType: ViewControllerType {
}

final class RootPresenter<VC: RootViewControllerType>: PresenterType {
    weak var viewController: VC?

    func bind(viewController: VC?) {
        self.viewController = viewController
    }
}

До этого момента все соответствует и отлично , но когда я начинаю реализовывать View Controller следующим образом:

protocol RootPresenterType: PresenterType {
}

final class RootViewController<P: RootPresenterType>: UIViewController, ViewControllerType {
    let presenter: P

    init(presenter: Presenter) {
        self.presenter = presenter
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        presenter.bind(viewController: self)
    }
}

НемедленноЯ получаю следующее сообщение об ошибке:

Невозможно преобразовать значение типа 'RootViewController

' в ожидаемый тип аргумента '_?'

Я знаю, что protocols со связанными типами могут вводить некоторые ограничения, но этот пример довольно прост, и я не могу заставить его работать.Можно ли достичь чего-то, чего я хочу, или мне нужно искать какой-то другой, менее Swifty шаблон?

1 Ответ

0 голосов
/ 28 ноября 2018

Я не думаю, что то, что вы пытаетесь достичь, возможно из-за циклической зависимости между соответствующими ассоциированными типами протоколов PresenterType и ViewControllerType.

Подумайте на мгновение, еслиподозрительный код выше скомпилирован ... как бы вы занялись созданием классов RootPresenter или RootViewController?Так как оба зависят друг от друга, вы получите ошибки, подобные следующим:

Generic parameter error 1. Generic parameter error 2.

Как выКак видите, компилятор не может полностью разрешить общие параметры из-за связанных типов.

Я думаю, что вам лучше всего удалить связанный тип из одного или обоих протоколов.Например, удаление связанного типа из протокола PresenterType и обновление класса RootPresenter нарушает циклическую зависимость и позволяет вашему коду нормально компилироваться.

protocol PresenterType: class {
    var viewController: UIViewController? { get set }

    func bind(viewController: UIViewController?)
}

final class RootPresenter: PresenterType {
    weak var viewController: UIViewController?

    func bind(viewController: UIViewController?) {
        self.viewController = viewController
    }
}
...