In this article I’m going to introduce MVVM design pattern in iOS programming and of course with RxSwift.This article divides into two parts. In part 1 design pattern explained briefly and basics of RxSwift, and in part 2 , we have an example project of MVVM with RxSwift.
At first ,It’s better to explain why we should use design patterns? In short: In order to avoid our code getting spaghetti 🍝 and of course this is not the only reason. One of the reasons is testability . There are bunch of design patterns and we can point some of the popular ones to MVC,MVVM,MVP and VIPER. There is a good picture from NSLondon slides that compare design pattern to Distribution,Testability and Ease of use.
All of these design patterns have its own advantages and disadvantages but in the end, each of them makes our code cleaner, simpler and easier to read.This article focuses on MVVM, which I hope you’d realize the reason at the end of part 2 .
So let's take a brief look at MVC and then we proceed to MVVM
You are probably familiar with MVC if you have been coding in iOS for a while ( Apple suggests using MVC for iOS programming ).This pattern composes from Model,View and Controller in which the controller is responsible for connecting model to view.In theory, it seems that the view and the controller are two different things but in iOS world, unfortunately, these two become one thing ( mostly ) . Of course everything seems well ordered in small projects but once your project gets bigger, controller almost has most of the responsibilities ( also named as Massive View Controller :D ), which leads your code becoming a mess, but if you can write MVC in correct way and divide your controller as much as you can, the problem will be resolved ( mostly ).
Well MVVM stands for Model,View,ViewModel in which controllers, views and animations take place in View and Business logics, api calls take place in ViewModel. In fact this layer is interface between model and View and its going to provide data to View as it wants. There is point that if you see following code in your ViewModel file you probably made a mistake somewhere :
because ViewModel shouldn't know anything from view, In Part II we will examine this article with a precise example.
One of the MVVM’s features is binding of data and view, which makes it pleasant with RxSwift.Of course you can do this with delegate,KVO or closures but one of the RxSwift’s feature is that if you learn it in one language you can reuse it on other languages too, because basic of Rx is same in languages that it is supported ( you can find list of languages here ). Now in this part we are going to explain the basics of RxSwift which are basics of Rx world as well. Then in part II we’ll have a project in MVVM with RxSwift.
Well RxSwift is based on reactive programming, so what does that mean?
In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow. — Wikipedia
Probability you didn't understand anything of this paragraph after reading it. We maybe it would be better to understand it with the following example:
Imagine you have three variables ( a,b,c ) like :
Now if we change
a from 1 to 2 and we print
c its value remains 3.But things are different in reactive world and
c value’s is depend on
b it means if you change
a from 1 to 2
c value is change from 3 to 4 automatically and its not necessary to change it yourself.
Now let's start RxSwift basics:
In RxSwift (and of course Rx ) world everything is stream of events ( including UI events , network requests , …) now remember this in your mind I will explain with real life example:
Your phone is an Observable which produces events for example ringing, push notifications , … which makes you to pay attention and in fact you subscribed to your phone and decide what to do with these events for example you sometime dismiss some of notifications or you answer some of them,… ( in fact these events are signals and you are an observer and making decisions)
Now let's do with code:
Observables and observers (subscribers):
In Rx world some of variables are Observable and the other are Observers ( or subscribers) .
Hence Observable is generic you can make observable from any type you want if it confirms to ObservableType protocol.
Now let's define some observables:
In first line of above example we have observable of String in line two we have observable of Int and at last we have observable of dictionary , now we should subscribe our observable values so we can read from emitted signals
It may question comes in your mind what are
completed in output and just why ‘hello world’ is not printed well here I must say maybe the most important feature of Observables:
In fact every observables are sequence which the main difference with swift sequence is that its value can be asynchronously .( if you didn’t understand these two lines it’s not important that much , hope you will understand with following description ) if we want say with image:
In above image we have three observables which first one is type of Int and emitted 6 values of 1 to 6 in time then it has been completed.In second line we have observables of string and emitted ‘a,b,c,d,e,f’ in time then some error has occurred and it has been finished.At last we have observables of gesture then it has NOT been completed and it continues.
In Rx world for every observable in its persistent time emits 0 to … number of events ( above example ) which these events are enum consist of there 3 probable values:
- .next(value: T)
2. .error(error: Error)
When Observable adds value/values the
next event is called and value/values are passed to subscribers(observers) via associated value property ( the 1 to 6 numbers , a to f and taps in above examples ).
If observable faces error ❌, the error event is emitted and observable has finished. ( after emitting
f in above example )
if observable completes, .completed event is emitted ( after emitting 6 in above example )
If we want to cancel a subscription and unsubscribe from an observable we can call dispose method or if you want this method called when your view deinits you should make variable with DisposeBag type and this variable do the work for you when your class deinitilized. I must say if you don't remember this your subscribers will make memory leak☠️💀. for instance observables should be subscribed like this:
Now let's see beauty of combining Rx with functional programming . Imagine you have observable of Int and you have subscribed to it, now that observable will give you bunch of Ints, you can do lots of changing on the emitted signals from observable for example:
For changing signals before it reaches to its subscribers you can use map method , for instance we have observable of Int which emits 3 numbers of 2,3,4 now we want numbers multipled by 10 before reaching its subscriber we can do this with following code:
You may want filter some of values before reaching to subscribers for example you want numbers that are above 25 in above example:
Imagine you have two observables and you want combine them into one observable:
In above example observable A and observable B are combined and made new observable :
DistinctUntilChanged or Debounce:
These two methods are one of the most useful methods in searching. For example, user wants to search a word ,you probably call search api every character when user typed. Well, if the user types quickly, you are calling many unneeded requests to the server. Correct way of achieving this is to call search api when user stops typing . To solve this problem, you can use the Debounce function :
In above example if username text field changes under 0.3 second those signals are not getting to subscribers so the search method isn't called and only when user stopped after 0.3 sec, signal will received by subscribers and search method is called.
The DistinctUntilChanged function is sensitive to changes, meaning that if two signals get the same signal until the signal does not change, it will not be sent to subscriber.
The Rx world is much bigger than what you can think of, and I just told a few basic concepts that I think would be needed in the next part of the article, which is a real project with RxSwift.
The RxSwift from raywenderlich describes very well RxSwift from 0 that I highly recommend reading.
You might not notice much about RxSwift from just one article because it’s one of Swift’s advanced concepts, and you might have to read different articles every day to find out. In this link you can see several good articles from his RxSwift section.
Hopefully, with the next part of the article that Rx introduces into the real project with MVVM, you will understand the concepts of RxSwift because it will be much easier to understand with real examples.
My twitter id is Mohammad_z74, and my email email@example.com✌️