Many VIPER guides focuses only on VIPER and not how it fits in with the rest of your application. If you want to get our view on a good overall architecture for your app and use VIPER, then this is an article for you. VIPER can be switched out with any other architecture if you want.
A practical example and explanation on how to setup viper together with the rest of your application.
Consider the following diagram
Here we are integrating VIPER into other modules like AppCoordinator, Data Repositories and a Session Manager. We found that this is a good layout for many applications and i will try to explain how we did it.
Each VIPER module is made up like this
But this article is not directly about VIPER. If you want a more in depth explanation of VIPER, then i recommend reading Implementing VIPER Architecture Pattern for iOS.
Let’s discuss the objects and their responsibility in our architecture
A collection of reusable components, like buttons, views etc. Components is something the user can see.
A collection of reusable helpers, like dateformatters etc. Helpers is something that computes stuff.
Handles starting the application and booting the AppCoordinator together with SessionManager and DataRepository. Forwards lifecycle messages to the AppCoordinator.
Manages the user session — is the user logged in or not and also takes care of the login/logout process.
All communication back and forth between the app and the backend and handles stuff like caching for offline use.
Coordinates the main lifecycle events of the app — takes decisions on starting up, delegating messages and switches the main app flows depending on login status.
A typical app have 3 overall “areas” (or states) where the user can be and therefore it’s a good place to have the coordinator to coordinate this depending on user state.
- Splash on load
- Login flow when user is logged out
- Normal App flow when user logged in
Below you can see how we initialize and starts the coordinator.
You need to initialize a DataRepository and a SessionManager and pass them to the AppCoordinator. We like to avoid singleton classes and therefore we need to inject the dependencies that are required for the coordinator and modules to run.
The code for the app coordinator looks like this
Now the app will switch out the active VIPER module based on user state. The coordinator could also take care of delivering messages to the right modules or queue them until the user is logged in or telling the data repository to save its state when user exits the app.
Just to give an example of how the actual VIPER module is started you can check out the following Router for the LoginSelectionModule. (Where you choose how to login or if you want to sign up).
That’s about it and how we integrate VIPER into our iOS apps. Feel free to comment if you have any thoughts.