Home > Mobile >  iOS MVVM with RxSwft: what is the drawback with viewmodel everywhere?
iOS MVVM with RxSwft: what is the drawback with viewmodel everywhere?

Time:12-28

RxSwft is very suitable for iOS MVVM.

Putting viewmodel everywhere, disobeys Law of Demeter ( The Least Knowledge Principle ).

What is the other drawbacks?

Will it leads to Memory Leakage?

Here is an example:

ViewController has a viewModel

ViewModel has some event signals, like the following back event

class ViewModel{
     let backSubject = PublishSubject<String>()
}

ViewController has contentView and viewModel, and contentView init with viewModel

    lazy var contentView: ContentView = {
        let view = ContentView(viewModel)
        view.backgroundColor = .clear
        return view
    }()

and ViewModel's various subject are subscribed in viewController to handle other part view

viewController is a Dispatch center.

ViewModel is Event Transfer station. ViewModel is in everywhere, in Controller, in View, to collect different event triggers.

the code is quite spaghetti


in ContentView, user tap rx event , binds to the viewModel in viewController

tapAction.bind(to: viewModel.backSubject).disposed(by: rx.disposeBag)

user events wires up easily.

But there is memory leakage actually.

So what's the other disadvantages?

CodePudding user response:

ViewModel doesn't break the Law of Demeter but it does break the Single Responsibility Principle. The way you solve that is to use multiple view models, one for each feature, instead of a single view model for the entire screen. This will make view models more reusable and composable.

If you setup your view model as a single function that takes a number of Observables as input and returns a single Observable, you will also remove any possibility of a memory leak.

For example:

func textFieldsFilled(fields: [Observable<String?>]) -> Observable<Bool> {
    Observable.combineLatest(fields)
        .map { $0.allSatisfy { !($0 ?? "").isEmpty } }
}

You can attach the above to any scene where you want to enable a button based on whether all the text fields have been filled out.

You satisfy the SRP and since object allocation is handled automatically, there's no concern that the above will leak memory.

CodePudding user response:

You are right, there are some drawbacks, if you want just a data-binding, I would suggest to use Combine instead, since no 3rd party libraries need, you have it already. RxSwift is a very powerful tool when you use it as a part of language, not just for data binding.

Some of suggestions from my experience working with RxSwift:

  1. Try to make VMs as a structs, not classes.
  2. Avoid having DisposeBag in your VM, rather make VC subscribe to everything(much better for avoiding memory leaks).
  3. Make its own VMs for subview, cells, child VC, and not shared ones.

Since your VC is a dispatch centre, I would make a separate VM for your content view and make a communication between ContentView VM and ViewController VM through your controller.

  • Related