我在新项目中使用CleanSWift
,但我觉得它太罗word了。为了使一些基本的东西自动化,我编写了以下工具(简化了):
// 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. **
}
有任何想法吗?谢谢。
最佳答案
当前,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子句约束,同时提供typet安全,通用的MyPresenter
实现。这种方法有一个局限性:您不能为
viewController
的单个实例更改MyPresenter
值的类型。