swift - 在泛型函数中使用协议(protocol)的关联类型

标签 swift swift-protocols

我正在尝试编写一个简单的 MVP 模式以在我的应用程序中遵循,因此我编写了两个协议(protocol)来定义 View Controller 和演示者:

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)
}

在定义了这些之后,我开始编写一些 RootViewControllerRootViewPresenter。后者看起来像:

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)
    }
}

我立即收到以下错误消息:

Cannot convert value of type 'RootViewController

' to expected argument type '_?'

我知 Prop 有关联类型的 protocol 会引入一些限制,但这个示例非常简单,我无法让它工作。是否有可能实现我想要的东西,或者我是否必须寻找其他一些不那么 Swifty 的模式?

最佳答案

由于 PresenterTypeViewControllerType 协议(protocol)的各自关联类型之间存在循环依赖关系,我认为您无法实现您想要实现的目标。

考虑一下,如果上面的可疑代码确实编译了...您将如何实例化 RootPresenterRootViewController 类?因为两者相互依赖,所以您最终会遇到如下错误:

Generic parameter error 1. Generic parameter error 2.

如您所见,由于关联类型,编译器无法完全解析泛型参数。

我认为最好的办法是从一个或两个协议(protocol)中删除关联类型。例如,从 PresenterType 协议(protocol)中删除关联类型并更新 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
    }
}

关于swift - 在泛型函数中使用协议(protocol)的关联类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53507364/

相关文章:

swift - 使用从另一个协议(protocol)继承或使用 where Self 声明 swift 协议(protocol)时的区别

swift - 为什么 swift 编译器在有/没有 Equatable 协议(protocol)的情况下对相等运算符的行为不同

ios - 无法通过 segue 将图像从 uitableViewCell 传递到细节

ios - 如何在单元测试中以编程方式点击 UIImageView?

ios - 云 Firestore Swift : How to delete a query of documents

ios - SDWebImage 不会在真实设备上显示本地存储的图像,但会显示在模拟器中

swift 3 : Inheritance from non-named type

swift - 在 Swift 中使用具有约束关联类型的协议(protocol)作为属性

Swift协议(protocol)继承同名协议(protocol)方法

SwiftUI 删除 NavigationView 列表顶部的间距