I was going through this link.
But I dont really get the logical difference between the below two code snippets:
1. Extending ONLY those UIViewControllers which conform to protocol ErrorPopoverRenderer .
protocol ErrorPopoverRenderer {
func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool)
}
extension UIViewController: ErrorPopoverRenderer { //Make all the UIViewControllers that conform to ErrorPopoverRenderer have a default implementation of presentError
func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool)
{}
}
2. Extending the protocol for ONLY those UIViewControllers which conform to it.
extension ErrorPopoverRenderer where Self: UIViewController {
func presentError() {
}
}
Either ways, Any UIViewController subclass which will conform to the protocol will have default method implementation but in UIviewcontroller extension OR protocol extension. What is the logical diffference? Please correct me if I am wrong
The difference is that the first:
extension UIViewController: ErrorPopoverRenderer { }
actually extends UIViewController
class, so every instance of UIViewController
has now access to methods & properties from the protocol. It doesn't mean that it will extend the class that implements the protocol, it means that right now you are implementing the protocol for this class. Usually you have to implement some of the methods & properties in that extension.
Where in second one:
extension ErrorPopoverRenderer where Self: UIViewController {}
you actually add methods & properties for UIViewController
that implements the protocol ErrorPopoverRenderer
.
Basically in first you extend the class with whole protocol implementation, and in the second one you extend class, but only if this class or subclass implements the protocol ErrorPopoverRenderer
.
1
First of all, you create a protocol ErrorPopoverRenderer
with a blueprint for method presentError(...)
. You thereafter extend the class UIViewController
to conform to this protocol, by implementing the (compulsory) blueprint for method presentError(...)
.
This means that you can subclass UIViewController)
with additional protocol constraint ErrorPopoverRenderer
for the subclass. If UIViewController
had not been extended to conform to protocol ErrorPopoverRenderer
, the subsequent code in the example you linked would case compile time error (... does not comply to protocol ErrorPopoverRenderer
)
class KrakenViewController: UIViewController, ErrorPopoverRenderer {
func failedToEatHuman() {
//…
//Throw error because the Kraken sucks at eating Humans today.
presentError(ErrorOptions(message: "Oh noes! I didn't get to eat the Human!", size: CGSize(width: 1000.0, height: 200.0))) //Woohoo! We can provide whatever parameters we want, or no parameters at all!
}
}
However, there is a possible issue with this method, as presented in your link:
Now we have to implement every parameter every time we want to present an ErrorView. This kind of sucks because we can’t provide default values to protocol function declarations.
So of the protocol ErrorPopoverRenderer
is not intended solely for use by UIViewController
:s (or subclasses thereof), then the solution above isn't very generic.
2
If we want to have a more broad use of ErrorPopoverRenderer
, we place the specific blueprints for each class type that might make use of the protocol in protocol extensions. This is really neat as the more specifics parts of ErrorPopoverRenderer
blueprints for method presentError()
can be specified differently for different classes that are to possibly conform to the protocol, and the method presentError()
can be made more minimalistic.
I quote, from the example:
Using Self here indicates that that extension will only ever take place if and only if the conformer inherits from UIViewController. This gives us the ability to assume that the ErrorPopoverRenderer is indeed a UIViewController without even extending UIViewController.
In this method, since the code now knows (we did, already in 1.) that it is a view controller that will call presentError()
, we can place the specific UIViewController
stuff directly in the blueprint implementation, and needn't send it as a long list of arguments.
Hence, 2. is, for this specific use, a kind of more "generic" approach, in the sense that we slightly minimise code duplication (calling presentError()
vs presentError(... lots of args ...)
from several different UIViewController
:s).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With