Learn how to design the same system using POP.
- [Instructor] Now let's redesign our UI components using a protocol oriented approach. We start with defining our protocols first. We're going to create dedicated protocols for each feature set. As a quick remark, we're going to follow the swift naming guidelines. Regarding protocol names, the rules are clear. Protocols that describe what something is should read as nouns. For example collection. Protocols that describe a capability should be names using the suffixes able, ible, or ing.
Like equatable or progress reporting. Since our protocols describe capabilities, we're going to use the second form. Alright let's open up xcode and create a playground project. We need a playground. Blank project is good. And I'm going to call it protocol way. Let's remove the unnecessary stuff.
So let's create our first protocol. I'm going to call it animatable. It declares the only animation related method that we're going to use. That is called pulse. It takes a duration argument of type time interval. Next I provide the default implementation in a protocol extension. Confirming types don't have to implement the first method unless they require a different behavior.
The code is the same that we used in super class example. To recap, we rely on the UI view's animate method so I'm going to call UI view's animate method, I need the one with a completion block, and the first half of the animation will take only half the time. The animation is simple. We gradually decrease the view's alpha. And in the completion block we don't need the boolean so we just remove it and in the second half we'll gradually increase the alpha value back.
By calling UI view animate again, but this time don't need the completion block and it takes only half of the overall time and the animation is self dot alpha and let's increase it back to one. Now we have a compiler error. It says the type self has no member alpha. This is because the animatable protocol has no reference to the UI view.
So we have to restrict this extension to the UI view. I am going to add the UI view type to the animatable extension by saying where self is of type UI view. And now our code compiles fine. What that means is that only UI view and UI view subclasses will receive the first functionality defined in the extension. Our next protocol declares the Custom Border related properties.
So I'm going to call it borderable. It declares two properties. One of a corner radius which is of type cg float. It is a gettable property. And a border width property which is also a cgfloat. And it's grid only as well. Again I'm going to provide default implementation for these properties in a protocol extension.
Where the corner radius of type cg float. The getter is going to return the layer's corner radius, and the center which sets the corner radius. Equals to new value and we must set the masks to bounds property to true.
We have the same problem as before so we must restrict the extension to types that are subclasses of UI view. Finally the border of each property of type cg float that returns a getter. Return self dot layer.
Now since we restricted the extension to the UI view type we get auto complete as well which we did not have before. And the setter which sets the border width. Equals to new value. Now we can create custom types which adopt the new protocols. I'm going to create the class called my view. It inherits from UI view.
Now let's make it adopt the animatable protocol. By doing so instances of this class will receive the pulse animation. Let's create an instance var my view equals my view out of frame just to keep it simple. And now I can invoke the pulse method on this very instance.
With a duration of a second, and by adopting the borderable protocol our view can also have custom borders. Let's add that too. And now I can set its borders. Its corner radius first. Let's make it 10 and the border width.
The best part, we don't have to write a single line of code to support the new pulse animation or to set custom borders in our types. All we need is to make our types adopt the animatable or borderable protocols. Or both if we need all the features. With protocol oriented approach we design a better and more flexible system. Our types can adhere to any or all the protocols without inheriting functionality they don't need. The responsibilities are clear.
And there is not code repetition. And we didn't have to write a single line of code as we defined the default implementation in the protocol extension.
- Comparing object-oriented programming with protocol-oriented programming
- Methods and class-bound protocols
- Adopting a protocol
- Declaring asynchronous behavior
- Preparing and implementing fallback logic
- Implementing an app using protocol-oriented programming