我正在与新项目中的CleanSWift
一起工作,但我觉得它太罗y了。为了使一些基本的东西自动化,我编写了以下工具(简化了):
// MARK: - Presenter
protocol Presenter {
associatedtype DisplayLogic
var viewController: DisplayLogic? { get set }
}
protocol PresentationLogic {
func show(_ error: Error)
}
extension PresentationLogic where Self: Presenter, Self.DisplayLogic: DefaultDisplayLogic {
func show(_ error: Error) {
}
}
// MARK: - Display logic
protocol DefaultDisplayLogic: class {
// func present(_ error: Error)
}
protocol TableViewDisplayLogic: DefaultDisplayLogic {
// func reloadTableView(with sections: [Section])
}
当我尝试实现上面的代码时,泛型似乎被破坏了。我收到一条错误消息,提示“类型'MyPresenter'不符合协议'PresentationLogic'。”但是,对我来说一切都很好。
// MARK: - Controller
protocol MyDisplayLogic: DefaultDisplayLogic {
}
class MyViewController: UIViewController, MyDisplayLogic {
}
// MARK: - Interactor
protocol MyBusinessLogic {
}
class MyInteractor: MyBusinessLogic {
var presenter: MyPresentationLogic?
func test() {
presenter?.show(TestError.unknown)
}
}
// MARK: - Presenter
protocol MyPresentationLogic: PresentationLogic {
}
class MyPresenter: Presenter, MyPresentationLogic {
weak var viewController: MyDisplayLogic? // ** Here I get the error. **
}
有什么想法吗?谢谢。
答案 0 :(得分:2)
当前,MyPresenter
不能满足PresentationLogic
扩展的where子句的要求,因此它不能使用show(_:)
的默认实现。具体来说,它没有通过Self.DisplayLogic: DefaultDisplayLogic
的测试。因此,它不符合PresentationLogic
,因此也不符合MyPresentationLogic
,后者继承自PresentationLogic
。
但是为什么不呢?我认为这是由Swift的工作方式引起的:协议无法符合自身要求。在MyPresenter
中,Self.DisplayLogic
是MyDisplayLogic
。尽管它是DefaultDisplayLogic
的后代协议,但它似乎仍然可以充当“试图符合自身的协议”,因此不起作用。
为证明这一点,您可以将weak var viewController: MyDisplayLogic?
替换为weak var viewController: MyViewController
,错误将消失,因为它是符合DefaultDisplayLogic
的具体类型。另外,如果将where子句中的Self.DisplayLogic: DefaultDisplayLogic
更改为Self.DisplayLogic == MyDisplayLogic
,则错误将消失,因为您需要的是特定类型而不是一致性。
在您的情况下,可能的解决方案是使MyPresenter
成为通用类。例如:
class MyPresenter<ConcreteDisplayLogic: DefaultDisplayLogic>: Presenter, MyPresentationLogic {
weak var viewController: ConcreteDisplayLogic?
}
这将允许您为show(_:)
的默认实现使用相同的where子句约束,同时提供MyPresenter
的类型安全的通用实现。
此方法有一个局限性:您无法为viewController
的单个实例更改MyPresenter
的值的类型。