UIViewController full initialization in MVVM

William Pompei
3 min readSep 18, 2019

--

UIViewController can be instantiated in different ways:

  • Storyboard
  • using one of the available init function

Both are viable, but some problems arise once you need to set up some controller's properties upon creation, such as the view model.

Using Storyboard you can initialize property in [prepareForSegue:sender:](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621490-prepareforsegue). The same happens with one of the provided init.

So you usually end up in writing similar code, using Optional or Implicitly Unwrapping property:

Optional property viewModel
Implicitly Unwrapping property viewModel

The problem isn't in the Optional/Implicitly Unwrapping choice, but lies in code semantics not aligned with the business logic.

If a property should be tagged as Optional if it isn't always defined by business requirement and not because of a code workaround. The same is for using Implicitly Unwrapping as its usage should be restricted to specific cases.

Morale: writing code is a difficult task by itself: please do not add unnecessary burden!

How to clean your code?

As an example, let's take a UIViewController used with MVVM pattern which needs a viewModel.

We should be able to achieve that result, as a view controller is useless without his view model, and to convey such information the viewModel property must be defined as follows (neither Optional nor Implicitly Unwrapping):

Updated controller code redefine UIViewController init() and init?(coder aDecoder: NSCoder) as unusable (to prevent accidental usage) and adds specific init(…) where the required properties are initialized:

Note: In the code above the nib used is implicitly the one with the same class name (ViewController.xib) because of nibName parameter equals to nil in super.init(nibName: nil, bundle: nil).

Bonus track to reduce code

It’s possible to avoid repeating the same code in each view controller (various init, viewModel property definition) by using class inheritance.

Define a class MVVMViewController as following:

Now you can extend your controller from MVVMViewController, by specifying the view model class type, and get the required init(viewModel: T) (with T corresponding to the view model type specified in the extension declaration MVVMViewController) and viewModel property already defined for you.

MVVMViewController in action using ViewModel as view model type

Bonus: MVVM using RxSwift

RxSwift needs a DisposeBag object for almost every view controller (unless the controller doesn't use any subscription or binding).

You can leverage MVVMViewController by adding a disposeBag property which is accessible from extending view controllers:

Sample RxSwift view controller extending MVVMViewController:

Stripped down ViewController without explicit disposeBag and viewModel property definition

Let me know your thoughts about this idea in comments 😄!

--

--