Reputation: 286
I am currently working on a Clean Swift (similar to VIPER) implementation. For each module I have a Presenter and a Displayer (which is a ViewControler in the end) all of it based on protocols.
Those are my generic Displayer and Presenter protocols:
// Generic Displayer
protocol BaseDisplayLogic: class {
func displayError(message: String)
func displayApiError(error: ApiError)
}
extension BaseDisplayLogic where Self: UIViewController {
func displayApiError(error: ApiError) {
if let errorDescription = error.errorDescription {
self.warningAlert(errorDescription)
}
}
func displayError(message: String) {
}
}
// Generic Presenter
protocol BasePresentationLogic: class {
var viewController: BaseDisplayLogic? { get }
func presentError(message: String)
func presentApiError(error: ApiError)
}
extension BasePresentationLogic {
func presentError(message: String) {
}
func presentApiError(error: ApiError) {
}
}
And here it is the implementation of a module I would need:
// A displayer
protocol RestorePasswordDisplayLogic: BaseDisplayLogic {
func displayPasswordRestore(ok: Bool)
}
class RestorePasswordViewController: UIViewController {
}
// A presenter
protocol RestorePasswordPresentationLogic: BasePresentationLogic {
func presentPasswordRestore(ok: Bool)
}
class RestorePasswordPresenter: RestorePasswordPresentationLogic {
weak var viewController: RestorePasswordDisplayLogic?
func presentPasswordRestore(ok: Bool) {
self.viewController?.displayPasswordRestore(ok: ok)
}
}
The problem is that I am getting an error in the Presenter implementation (RestorePasswordPresenter in this case) because it is not conforming to the BasePresentationLogic protocol. If I remove the
var viewController: BaseDisplayLogic? { get }
it works perfectly, but I need the viewController var to be visible from the BasePresentationLogic extension so I can make a default implementation of the presentError and presentApiError methods.
Any idea on that?
Upvotes: 1
Views: 246
Reputation: 299265
The direct problem is that you're not conforming to the protocol as required. You required a viewController
of type BaseDisplayLogic?
. So you need to create that, and store your more specific version in a backing variable:
weak var restorePasswordViewController: RestorePasswordDisplayLogic?
var viewController: BaseDisplayLogic? { restorePasswordViewController }
(Personally, and only as an opinion, I think this is wildly overusing protocols, and likely to be a source of many headaches, especially if you ever try to make these pieces generic and start needing type-erasers. If you've been successful with it, more power to you, but maintaining all these parallel class/protocol hierarchies seems a bad idea to me. It's reinventing class inheritance with protocols, which isn't what protocols are for, and they're not very good at it.)
Upvotes: 1