Updated: Protocol-Oriented MVVM in Swift 2.0

I’ve fallen in love with Protocol-Oriented Programming (POP), but of course, I’m new to it and still learning. One of my favorite use-cases for POP is with MVVM.

I wrote about it back in August – read it if you’d like to understand the problem more. Since then, I have of course found an even better way of applying POP to MVVM! I gave a few talks on this over the past few months, so I’m excited to finally write it down (I’ll also post the video versions when they come out).

The key was the amazing Mixins and Traits in Swift 2.0 article by @mhollemans. So here is the updated version:

I’m going to use a very simple example. A Settings screen that currently only has one settings – put your app in Minion Mode!, but you can of course extrapolate to multiple settings:

Simulator Screen Shot Aug 17, 2015, 8.26.21 AM

The Cell Components

You can split this cell into two components – a label and a switch. Those same components can be used in any other cell or view in your application. And they require the same exact configuration. So why not break out the required configuration into protocols?

Let’s say that most of the switches in your app have the same switchColor – you can use protocol extensions to easily set that up:

However, I recommend being careful with the protocol extensions. Make sure that the same configuration (e.g. color) is used in at least two places before making it the default implementation.

You can also extend the protocol extension configuration to be more specific. For example, let’s say you have a header label that is configured one way (big and bold font and color) vs a subhead label (configured with a smaller font and lighter color) across the app. You can create protocols with default implementation for these!

And of course, this extends to images, text fields, and whatever other components you’re using in your app:

The Cell

So now, you can use protocol composition to require an object that conforms to the new composed protocol to configure the cell:

The View Model

The View Model is now going to be that object that takes in the Model data, and processes it to conform to the SwitchWithTextViewPresentable protocol for presentation to the user.

The View Controller

So now, configuring the Table View Cell is super easy:

Say goodbye to the Massive View Controller!


For me, the thing that makes something a good pattern is how easy it is to change. After all, “Change is the only Constant” as the famous quote goes. That is especially true in Software Development.

So how does this pattern measure up? Let’s say a product manager wants to add an image to the cell. After adding the UIImageView in my Storyboard and adding it as an @IBOutlet to my cell, the next step would be to simply add the ImagePresentable Protocol to my protocol composition typealias:

The second step is to just add the additional protocol conformance to the View Model:

That’s it! Consider how much you’d have to change if you had to add an image to a cell in your app. Protocols make this easy – just add a protocol conformance requirement and have an object conform to it!

For more view protocol examples and implementation, check out the Standard Template Protocols library.

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.

  • finneycanhelp

    Nice article!

  • Super nifty! Thanks for explaining this Natasha!

  • devnikor

    I have a question about instantiating vm’s for cells:
    Suppose we have a view model for table view controller, that returns view models for every cell. So, should we create the all new view model for every cell, or we need to cache them?

    • Your view controller should have a variable referencing the master (array) view model. However, if one of the elements in the master view model changes, it’ll create a brand new view model with all the other view models and the new one.

      I would set up a mutating function that replaces the view model that is changed in the array of view models if that makes sense: https://www.natashatherobot.com/mutating-functions-swift-structs/

      • I made a note to write about it in the next week!

        • devnikor


  • Boram Han

    Hello. Natasha. I am new in MVVM. I have a question about business login such as network request:
    Where is good place to put it? View model or inside view controller?

    I create UserListViewModel for tableview and UserViewModel for cell. UserListViewModel has a two functions: userAtIndex(index), numberOfUsers().
    Now I am calling a network request on “view controller”, and then create new UserListViewModel with its result.
    If I put it inside UserListViewModel, should I use delegate for notifying updating view model’s data? What is right approach? Really confusing to me. 🙁

  • Hi Natasha,

    Thank your for the article, this is a great intro for iOS developers who’d want to use MVVM in their projects. I just have one question though, should the ViewModel be a struct or a class? Will turning it into a class make it future-proof since ViewModel’s might get mutated frequently when the project becomes more complex?

    • It should be a struct! That make it a lot safer. The ViewController can keep track of the latest copy to display to the user. Great talk here: https://realm.io/news/andy-matuschak-controlling-complexity/

      • Damir Štuhec

        I agree, BUT imagine a following scenario: cells have a UIScrollView subview with paging enabled. Since those cells are reusable, we have to keep track on which page the scroll view was left at for each cell in order to offset the content to the right page next time the cell gets reused.

        Here is the challenge. If presenter is a struct (value type) we cannot mutate it in order to store/update the “currentPage” property value on it.

        How would you tackle this challenge with structs?

        My thinking – part 1: have a delegate for this presenters and act upon every “page change” event by creating a new version of that presenter with updated “currentPage”.

        My thinking – part 2: make presenter a class which will allow direct mutation of a “currentPage” property when the “page change” event occurs.

        Thanks and keep up the good work! :+1: 🙂

        • Info Reqd

          quoting Charles here

          After being instantiated, how does the ViewModel struct get updated when the model receives a change (and while the ViewController is still open)?

          I’m trying to think how this View Model approach would work with TableViewControllers.

          Each cell, would be connected to a View Model
          And I’m guessing that the TableViewController will hold onto the Model that makes up the datasource. Lets say for discussion sake that the model is an array of objects that relate one-to-one with the cells in the table.

          So if the Model changes for a cell that’s visible on the screen, then the TableViewController will need to reload the cell at the index path related to the model appearing, and re-configure it with the new View Model (as the VM is immutable)

          Is this how you think too?
          If yes, the hard part will be applying an elegant way to find out which model objects changed so the changes are propagated down to the cell?

      • Charles Renwick

        Maybe a similar question to Damir,

        After being instantiated, how does the ViewModel struct get updated when the model receives a change (and while the ViewController is still open)?

        For a poor attempt at illustrating this, after the ViewModel is instantiated, data flow looks something like:

        Model –> (??) ViewModel –> ( didSet updates the view) ViewController

        Model <– (Model methods call the network) ViewModel <– (ViewModel methods)ViewController

        I can't simply rely on closures of the Model methods, because some model updates will happen without method calls provoking them (i.e, socket events).

  • Emilio Fernández

    Hi Natasha, wouldn’t it make more sense to have the view model’s SwitchWithTextViewPresentable implementation in the view? To clarify: to put the view model extension implementing SwitchWithTextViewPresentable in the view file(the view controller).

    IMO things the view model itself should not be aware about things like fonts and colors – that’s essentially responsibility of the view.

  • Thierry Bucco

    Very nice article, thanks a lot. I have 2 questions:
    1- Is it possible to add a model to your exemple? It would be even more interesting
    2- How would you do if your view needs 2 labels. I am using your exemple to construct a login page. I would use:

    loginLabel.text = presenter.loginLabelText
    passwordLabel.text = presenter.passwordLabelText

    What do you think?


    • George Marmaridis

      Did you find an answer to your problem? I’m facing a very similar one!

  • Roger Gonzalez

    Hi Natasha,

    I’ve bumped into your excellent post while trying to refactor code from a mega-ViewController to a bunch of smart Views that implement protocols (and may have a view model separate from the data model). It seems to work well for table cells as you’re doing here, but when I try to generalize the concept to an IB view with a custom UIView subclass, it still dispatches events to the VC instead. I’ve double checked all the actions and everything seems correct. Any ideas?


  • Thanks Natasha! Feeling very excited right now. 🙂 I’ll definitely try this out in my current project.

  • Thanks for sharing this Natasha! I’ve been trying to come up with a good UITableViewCell hierarchy for one of my apps and this post helped me finding a nice solution by using protocol extensions. I did a write up of my use case here: http://bizz84.github.io/2016/06/18/Protocol-Oriented-UITableViewCells.html

  • James Power

    Thanks for the article, I’m excited to try some of these ideas!

    Just a heads up, I think there is a typo for the word “toggle” – it’s spelled “togle” in a couple of places.

  • Cool. Would it be fair to say that we could extend this by creating a datasource property on the view controller of: let dataSource = [MinionModelView] and accessing the appropriate model with the indexPath in celForRowAtIndexPath…?