MVVM ❤️ RxSwift ❤️ Swift 4.x
Introduction
Oh yes! You’ve heard of the acronym MVVM
over and over again and it stands for Model-View-ViewModel
and I am focusing on this because I think it is the best and most realistic software architecture pattern for writing great iOS apps.
Why not MVC, MVP or VIPER ?
Well the intent of this article is not to go into a holy war with anyone but to share my personal opinion based on experience over the years as an iOS engineer.
MVC
The MVC
stands for Model-View-Controller
This is the most widely used architecture pattern within the iOS frameworks and most especially in the UIKit
there are tuns of examples and things really gets messy when you have Storyboards
within your application. MVC
pattern is not bad, but the way Apple
used this pattern in UIKit
is totally unhealthy and unacceptable. The UITableView
is a total tangle with zero separation of concerns. Apple
is suppose to champion high quality code and good architectural design for it’s platforms. But this is not the case I must admit that with the bad examples shown in UITableViewDatasource
& UITableViewDelegate
is enough horror for you to avoid MVC
totally.
MVP
So what problem do I have with this fantastic architecture pattern? First what’s MVP
? stands for Model-View-Presenter
This architecture is widely within the Android
development environment although it was first developed by Microsoft.
As shown in the image above, we see that MVP
is looking similar to MVC
with one subtle difference related to changes within the model. In MVC
the Model
can communicate directly to the View
oh yes! this was the horror that I was referring to eailier.
But wait MVP
doesn’t make this mistake? No it doesn’t. MVP
brings a very good separation of concerns and it’s perfect when you have to write a small app or prototype to show particular concept. The MVP
has two main problems which are as follows:
- The presenter tends to get involved with the
UI
related logics and becomes all-knowingClass
- Secondly the relationship between the
View
and thePresenter
is a one to one relationship. Which mean you can’t actually reuse thePresenter
for otherViews
so it does have a big issue on reusability.
VIPER
VIPER
stands forView-Interactor-Presenter-Entity-Router
this pattern is highly scalable and has a brilliant separation of concerns. Let’s break it down:
View:
Send user actions to presenter and displays data from presenter.Interactor:
Handles all the business logic. This is the core component.Presenter:
Queries theInteractor
for data and sends it to theView
Entity:
Holds model objects used by theInteractor
.Router:
Handles all navigation logic.
VIPER
is actually very good when working on a large code base because it enshrines the Single Responsibility Principle by helping you to decouple code for testability and reusability. It does this so well that you can consider yourself writing a “Ravioli” code :) if applied correctly.
So why am I not advocating for VIPER
? why do I think it’s not a good fit for iOS development ? Like I said before I don’t want to cause a holy war but here are my personal reasons:
- High learning curve for new team members.
- It’s highly opinionated by veteran engineers.
- It doesn’t fit or match with
UIKit
- Over decoupled into becoming a “Ravioli” code base.
- It’s overrated for what it offers when it comes to separation of concerns.
MVVM + RxSwift + Swift4.x
MVVM
is my pick here in this war of architecture patterns. I am not advocating that it doesn’t have pitfalls, but I think it makes sense to use MVVM
especially when writing iOS or Mac OS Apps. The original sin is thatMVC
has been totally misused by Apple
engineers in building tons of Spaghetti
code within the UIKit.
This was the problem all the other patterns were trying to solve. VIPER
for me is an overkill, MVP
has problem on reusability, Therefore MVVM
cuts in between and it does blends in very well. Here are my key points:
- Successful separation of concerns — Solid Principles where the
View
talks only to theViewModel
and theModel
talks only to theViewModel
. - Reusability — one to many relationship between
ViewModel
andViews
. - Testability — just mock the interface and you are good to go.
- Low learning curve — fast to learn.
- Less opinionated by veterans — almost everyone agrees.
RxSwift
Data binding is key part of MVVM
and this is where RxSwift
really play a great role in iOS App development. RxSwift is the Swift
implementation of the ReactiveX API for asynchronous programming with observable streams of data. It makes life really easy when abstracting logics and the data bindings becomes like a kid’s play.
Putting it all together [MVVM, RxSwift, Swift4.x]
Enough of talk, let’s build a real world app with all the information we have at hand. I am choosing the iPhone Contact View where you have the names grouped into sections based on the first Character
of the the lastname or firstname as show in the image bellow:
So let’s start by modelling a basic Person
data as follows:
Model:
We are going to stick strictly with the MVVM
pattern and as such our Model
is where the business logic resides. The Model
is responsible for the data access layer and any logic related. Yes the Model
can contain computations.
The implementation of our interface is pretty straight forward as we can see from the code below:
ViewModel:
The ViewModel
is responsible for all transformations, properties exposure to the View
, communication or interaction mediation between the View
& Model
The ViewModel
can be seen as the actual state of the underlying Model
The above code represents our interface requirement for the ViewModel
RxSwift — TableDatasource:
The RxSwift
base implementation for UITableView
doesn’t support the multi section UITableView
. I find this a little bit strange. It has the implementation in a separate library called RxDataSources within the RxSwift Community repository. By the way I advise you to look at community repository there are lots of cool libraries that can make your life easy.
Albeit for this task I want to stick with only RxSwift
so we are going to implement a utility Class
called TableDatasource
that will help us harness the multi section requirement as follows:
With that done we can now complete our ViewModel
implementation based on the requirement.
View:
The View
is responsible for displaying anything that the user can see. Yes your Autolayout
logics should be in the View
, and holds a ViewModel
and uses it to communicate use interactions.
Is UIViewController
a View
or a Controller
? Well in my personal opinion I sole treat any UIViewController
as a View
. You are free to interpret it as you wish, but for me it remains a View
in the context of MVVM
Composing MVVM:
Now we can actually plugin every thing together and see the MVVM
come to live as follows:
Conclusion:
These are my personal opinions, if you are super fan of other patterns please feel free to make constructive suggestions and rationals, I am open for discussion and I hope I’ve at least entertained you with my rant :) Thanks for reading. You can find the code examples on my playground repository which covers this article, feel free to distribute and have fun.