Protocol Oriented Programming in Swift

Don’t start with a class. Start with a protocol.

Fırat Onurcan Polat
4 min readOct 13, 2022
Photo by Dmitry Chernyshov on Unsplash

What is Protocol?

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.

Protocol Syntax

Protocols define interfaces that can be implemented by any struct, class, or enum:

Properties defined in protocols must either be annotated as { get } or { get set }. { get } means that the property must be gettable, and therefore it can be implemented as any kind of property. { get set } means that the property must be settable as well as gettable.

Some Protocol Pros

  • Types can conform to more than one protocol.
  • They can also obtain default behaviours from multiple protocols.
  • Protocols can be adopted by classes, structs and enums, while base classes and inheritance are restricted to class types only.
  • Protocols allow retroactive modeling with extensions added to existing types.

Why We Should Use It?

You might be wondering why you would need a protocol. Protocol comes in handy when writing unit tests. The protocol allows you to swap out a real use case implementation with a fake implementation while running unit tests. The protocol also allows you to hide concrete use case types from view controllers, or from any other objects needing to start use cases.

That’s enough theory. I wrote an application with pop as an example. You can follow the step-by-step explanations below.

The application saves the name and phone number of any person and displays them as a list. For clarity, I wanted it to be a single page and no detail ui stuff. Tableview consists of textfields and a button and stores data locally via coredata.

CoreDataManager

First I create my protocol named CoreDataManagerInterface for saving, pulling and deleting data. Then I create the CoreDataManager class that conforms to this protocol. In this way, when we come to the testing phase, we can easily create a mock class and write a test.

HomeViewController

First, we created our HomeViewControllerInterface protocol, which includes two functions called setupUI and showAlert, which we will use outside of our class. Then we conform our HomeViewController class from this protocol. Again, when defining our class, we use final because it will not be inherited in another class. We set up the UI with the SetupUI function, we show our warning on the screen under the conditions determined by our viewmodel with the showalert function.
By clicking the Save button, your savePerson function in our viewmodel will be triggered.

HomeViewModel

First, we add the functions and variables we need to the HomeViewModelInterface protocol, and then we start creating our HomeViewModel class from this protocol.
We define our coredatamanager and view variables in their own interface types and set them in init. The weak word before the view variable allows us to prevent memory leaks that may occur due to the retain cycle.

Unit Tests

Writing unit tests is just as important as writing application code. It will help in important issues such as the sustainability of our application, the reliability of the logic of our code, and whether the newly added features will have any side effects on our application. If you’ve come this far, don’t be afraid for unit tests ☺️

MockCoreDataManager

Since our logic stuff is in the homeviewmodel class, we will use our real homeviewmodel class and mock the dependencies of our viewmodel. We will use SwiftMockGenerator to mock our dependencies. We can write the protocol that our class will conform to and easily mock it as in the screenshot below.

MockHomeViewController

HomeViewModelTests

We create our Homeviewmodel. Then we create a mock version of its dependencies. The test naming standard is your choice, but as always, this choice should be able to understand what you’re testing and what the result will be when you or someone else looks at the code in the future.
We check the condition we are going to test before and after calling our function.

Writing unit tests is just as important as writing application code. It will take a little more time to make the first architectural structure of your application with the Protocol Oriented programming approach, but if we consider our applications as a living structure, adding new features will enable us to intervene more quickly and reliably to the problems that may arise.

Resources

Swift Protocol-Oriented Programming: Increase productivity and build faster applications with Swift 5, 4th Edition

https://tsh.io/blog/protocol-oriented-programming-swift/

https://www.youtube.com/watch?v=t5FHEwmZJ0I&t=1745s

--

--