Architecting an iOS app is not an easy decision, many factors should be considered when building an app, after all following an MVC or MVVM will cover a part of what you are trying to solve but there is no silver bullet and still there will be need to think about how to build and architect the business layer and data layer more effectively, multiple articles did discuss the pros and cons of famous app patterns, like this one in Medium, it is good to use your software engineering skills in building a maintainable, modular, scalable, testable robust app.
I will address mainly the MVC, MVVM, MVP and VIPER patterns through building this simple very common use case with each one:
- Display a list of simple media objects (Photo + Title) in a grid, Data is retrieved through a restful api call from :
Now lets start with VIPER, the diagram below should give you an overview of how classes are structured
Following a POP(Protocol Oriented Programming) approach, The VIPER stack will be declared in protocols presenting input and output for every entity, mainly the following protocols:
Other protocols might be added according to the use case, e.g. ViewControllerDelegate or e.g. DataManagerProtocol
Now breaking the diagram above :
View: mainly UIView objects, nib files, Storyboards, ViewControllers.
The ViewController manages different UI Objects (e.g. CollectionViews, DataSources), normally it is the source of view objects and it conforms to the PresenterOutput where communication is done through it.
for our use-case, I used the following files to manage the view layer:
Presenter: consists of two protocols PresenterInput and PresenterOutput protocols, The Presenter class conforms to PresenterInput and InteractorOutput, The presenter class communicates with Router/Wireframe for UI Navigation , one of the most important roles of the Presenter is to provide the View layer with models ready for presentation.
Interactor: consists of two protocols InteractorInput, InteractorOutput, Interactor class conforms to InteractorInput Protocol and the output is a delegate property in the presenter, the Interactor communicates with the outer world of data and carries business logic, target is to convert Simple DTOs retrieved from Data Layer to App Models
if you don't have lots of time to do tests ( which is really bad) make sure to at least cover the Interactor class properly, as the business logic happens here.
Entity: What the Interactor communicates with to retrieve data, this could be the Data Access layer and Simple Plain Models (note some writers/bloggers consider the DataAccessLayer to be part of the Interactor and that Entity are the simple plain objects only, It is really up to you how you would divide the architecture.
Router: responsible for navigation and hooking, Communicates only with the Presenter
The folder structure screenshot might also be helpful:
Where to go from here?
This is just a one use case, however it scales smoothly, I would advise to use the same strategy but with a cluster for use cases , having a root wireframe and cluster wireframe, at the beginning VIPER might be confusing and takes some time to grasp, but it is really beneficial in maintaining and developing a modular code base.
IMO also it might not be always the best solution, I recommend it for application which are expected to grow largely and with many contributors, but for small limited number of screen apps, it might make sense to go with a faster approach such as MVVM or MVC
The full code for the developed use case can be found here