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