For a Mobile Development project defining the type of architecture is very important, but how do we know if the one we choose is the right one?. One mistake that most iOS developers do is put all the logic in the controllers (Massive View Controller), this is a huge problem because the classes become hard for maintenance and also create unit tests for each of them.
Apple gives us the MVC pattern architecture, but it does not follow a common structure like any other languages such as C#, Java or Ruby. The reason behind this is because the controller contains the UI elements which in most of the cases leads developers to confusion of what should be the correct separation of tasks and responsibilities.
For all of these reasons our iOS team decided to research about different solutions for this problem, we tried VIPER and MVM but the results didn’t fulfill entirely our expectations, but then we found it!, the answer was Clean-Swift.com, this awesome architecture allowed us to test our code the way we wanted.
One word … Fast.
The great beauty of Clean Swift is the ability to quickly create scenes for each controller, let me give you quick example, let’s say that you need to create a LoginViewController, in a common development process you’d need to do all from scratch. With Clean Swift you may just need to go to their oficial website where you’ll be able to download the initial templates to start a scene and simply create a new one called Login, after doing this you’ll get all the necessary layers to start working on the scene, just … like … that!
I’ll explain you each layer that one scene has:
- Controller: This is the normal controller that Apple give us, but it has all setup ready to make the communication with the other layers. This component is in charge of connecting the UI with the code, I need to stress out how important is to say that it must not have complex logic.
- Interactor: This component handles all the logic decisions, serving as bridge between communications, it receives the action to make a login but it does not contain the logic. His function is to know who’s in charge of doing the login process.
- Worker: This component is the helper of the Interactor, in the login case the worker must know how to make the login and it should return an answer to the interactor with the result of the operation.
- Presenter: This is a presentation layer, it should parse all the data to the controller in the correct format. For example if we have an app that presents Dates, usually the logic’s format is implemented in the controller or helpers (in the best case), but with this architecture the rules change. The presenter should receive a NSDate and make the format, then it should send to the controller as a string, with that information the controller only needs to do something like this: dateLabel.text = Presenter.date. In summary, this layer spares the controller to make all the necessary logic to present data to the user.
- Models: This is the channel to pass the messages between the layers. The cycle is the following, the controller makes the request, the interactor process the request and sends a response to the presenter which processes the response and sends a view model to the controller, in this case the controller only needs to show the information contained in the view model. Well all of this is posible with the Model, it is in charge to keep the communication between layers.
- Router: This layer is in charge of the navigation of the scene. All tasks related with navigation should be here.
- Configurator: This component is in charge to keep all the Clean Swift cycle in the scene. Most of the time you will not need to work on this class. As it’s name says, is the configurator of the scene that makes the entire flow to work correctly.
Now that all have the concepts clear for each layer. I’ll explain you how the communication between the layers work.
The first thing is, all the communications between the layers use delegates, each layer has inputs and outputs.
For example if we have a controller called LoginViewController, we could need the following action, makeLogin. In that case we are going to need an output to request the makeLoginAction also an input to know the result of the action makeLogin. The same thing happens with the Interactor and the Presenter.
If you are interested to see how this architecture works in a real application, you can check this repo: https://github.com/cbrenes/PurchaseList