Tuesday, September 19, 2017

Swift - MVVM - RXSwift Instead of didSet()

In this post, Let’s see why we need to go for a reactive binding than to simple go for didSet() or KVO.

As we are all aware, In MVVM (Model-View-ViewModel), ViewModel and View should have data binding.
Whenever some variable in ViewModel changes, View should automatically doing the necessary stuff.
That’s the basic of MVVM design pattern. 

Now here the question is, How this binding can be done. 
View needs to observe for the changes in ViewModel and should be doing something based on the changes.

Let’s take an example of array in a ViewModel, Based on which we need to reload the tableview in View.

Let’s see disSet() helps us for this or not.

Here is my sample ViewModel class which is having a array of strings variable.

----------------------------
-----------------------------------------------------------------------------


class ViewModelClass {
    
    var arr: [String] = [] {
        didSet {
            didSetArr()
        }
    }
    
    func didSetArr() {
        print("\(arr.count)")
    }
}


----------------------------
-----------------------------------------------------------------------------

Let’s see changing the array content is calling the didSet() as expected or not.


----------------------------
-----------------------------------------------------------------------------

let viewModel = ViewModelClass()
var name1 = "Name1"
var name2 = "Name2"
viewModel.arr = [name1, name2]
viewModel.arr   //["Name1", "Name2"]

----------------------------
-----------------------------------------------------------------------------

Only count got called 2 times as I have just initialised the array with 2 elements. That’s fine.

Let me change an element in the array and see the call.


----------------------------
-----------------------------------------------------------------------------

viewModel.arr[0] = "Name11"

----------------------------
-----------------------------------------------------------------------------

Still 2 times didSet() is called. But It we need it to be called 3 times as there is a change in the first element of the array.

Let me change both the array elements and see the didSet() call.

----------------------------
-----------------------------------------------------------------------------

viewModel.arr[0] = "Name11"
viewModel.arr[1] = "Name22"

----------------------------
-----------------------------------------------------------------------------


Yo! 3 times of didSet() call. 

What is happening here?

The problem with didSet() is, It will get called only once the entire array gets updated.
When I changed both the elements in the array (entire array content), didSet() got called.

So, If we relay on didSet() for data binding, Our tableview in the View will not be displaying the latest array data.

That’s why we can’t relay on didSet() for collections where we can relay on didSet() for primitive types (Bool, String,….)

We need to go for RX to make a proper supposed data binding.


Hope this post is useful. Feel free to comment incase of any queries.