Swift 2.0: Protocol-Oriented MVVM

UPDATE: Read this instead for the most up-to-date implementation.

Ever since the mind-blowing Protocol-Oriented Programming in Swift WWDC Session, I’ve been thinking a lot about using protocols. But in reality, I haven’t really been using them as much. I’m still digesting what protocol-oriented programming means, and where in my code I should be using it instead of my other go-to programming patterns.

So I was very excited where a HUGE use-case came to mind. MVVM! I already use MVVM – see my earlier MVVM blog post if you’d like to learn more. And adding in protocol-oriented just clicks here!

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 View Cell

A cell that has a label and switch button is very generic. You can use this same cell in multiple places – a “Remember Me” setting on a Sign-In screen comes to mind for example. So you want to keep it as a generic view.

A Big Configure

Usually, I use a configure method in my cell that keeps track of all the possible settings different parts of my app that use that cell need. So it would look something like this:

With Swift’s default parameters, adding additional settings to the configure method without breaking all the other places in your code that uses is super simple. For example, when a designer comes and says that the switch color should be different, I just add that as a default parameter:

While this might not seem like a big deal in this case, in reality, my configure methods become super long and complicated over time! This is where the cool Protocol-Oriented way comes into play…

The Protocol-Oriented Way

And what happens when the designer wants to add the ability to change the default color? This is where the magic of protocol extensions comes into play!

The protocol extension implements the default switchColor option, so anyone who has already implemented this protocol or doesn’t care about setting a color, doesn’t need to worry about it. Only the new cell that has the one different color can implement it.

The ViewModel

So now, the rest is easy. I’m simply going to have a ViewModel for my MinionMode Setting cell:

The ViewController

The final step is to pass my view model to the cell when configuring the cell in the ViewController:

With protocol extensions, protocol-oriented programming is starting to make a lot of sense and I’m looking forward to figuring out ways to use it more! You can get the full code sample on Github here.

UPDATE: Separating the Data Source and the Delegate

In the comments below, Marc Baldwin suggested separating out the cell’s data source and delegate into two protocols, just like UITableView does, and I LOVE that idea. Here is what that would look like:

The View Cell

The cell would have two protocols, and it could be configured with both:

The ViewModel

You can now separate out the data source vs delegate logic in an extension:

The ViewController

This is the part I’m not as sure about – the ViewController will now pass in the viewModel twice:

I updated the code on Github here!

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

  • I was wondering wether the name “delegate” makes sense in this context? since you populate the cell with data through the delegate as well. I always think of delegates as pointers to functions, but in this case its more than that. What are your thoughts on that?

    • I feel the term data source makes more sense in this piece of code: label.text = delegate.title

    • Marc Baldwin

      I’d probably suggest following the approach used by UITableView and use two protocols; one for the source of data i.e. SwitchCellDataSource and one for the action i.e. SwitchCellDelegate. This practise is known as the Interface Segregation Principle and is the I in SOLID. See https://en.wikipedia.org/wiki/Interface_segregation_principle

      • Good idea! I really like that.

      • Cool, thanks :).

      • I updated the blog post with this as an example.

        • Steve Riggins

          Presentation in the delegate always gets me. UITableViews do this, but what if you want to have your presentation be A/B testable outside of what happens when a switch is selected? Does your delegate have its own delegate?

          • If you call it XYZDelegate, it sure sounds ridiculous — but deferring the decision of which A/B testing value should be used in a request sure is the concern of an object different from the delegate.

  • Bob

    First thank you for this wonderful article. Is it ok to make the MinionModeViewModel’s init like the following init(controller:UIViewController) {…} ? if I need a reference for my controller in the ViewModel.

    • You should not have to reference your controller in your view model. That’s a big code smell. What are you trying to do?

      • Bob

        What if I want to push a view controller after responding to an event. For example : in your code let’s say you want to push a controller if the switch is on. How can we deal with that ?

        • The ViewModel should send out an NSNotification – “viewModelDidChange” – the view controller will listen to the notification and act on it (in your case, by pushing another view controller).

          • Bob

            Thank you for the clarification:)

          • Srdan Rasic proposed an interesting technique using didSet property observers as an alternative to full-blown notification posting which I’ve written about here, if Natasha doesn’t mind linking to my own blog (sample at the bottom): http://christiantietze.de/posts/2015/01/mvvm-cocoa/

            I have forked Natasha’s repo and incorporated the changes:


            Using that technique, changes to the view model will reflect in the view immediately if you want. (Or, in this case, trigger pushing another scene.) That’s coupling the view model to the view instead of the controller, or: it results in a (live) model of the view.

            Now that’s odd since MinionModeViewModel already has onSwitchTogleOn(_:) as callback. In a real application, I’d implement the SwitchWithTextCellDelegate in a separate object, an event handler, so to speak, which would perform changes on the view model in memory. The view model object would then not implement both protocols.

            I propose something along the lines of:

            The delegate does respond to actions now, and that’s it. I think it shouldn’t know about colors and fonts. The MinionModeViewModel may, instead, because its minion-esque appearance depends on these properties as well.

          • Rusty

            Using NSNotifications to communicate from a model that a viewController owns is even more code stink than back referencing. delegation is the solution! Delegation is used to great effect all over this article.

            Simply define a delegate protocol

            protocol ModelViewChangedDelegate {

            func modelView(mv:MinionModelView, switchDidChangeValue switchIsOn:Bool)


            then add a weak var delegate: ModelViewChangedDelegate property to your MinionViewModel and, when you need to respond to events inside your vm, you call delegate.modelView(self, switchDidChangeValue:on)

            Then your viewController can respond to the change and the viewModel doesn’t know anything about the vc.

            NSNotifications are wonderful when you have system wide, asynchronous, disconnected, non-deterministic events. Using them for general control flow creates a troubleshooting nightmare.

  • Mark Oruba

    Hi, great article..

    I have read many times regarding MVVM that the ViewModel never should have any reference to the view aka (import UIKit) I know in the sample it is being used just for the color but it is correct?

  • loveforgeter

    very clear!

  • JB GonnaGo

    Is there an ‘in a nutshell’ few sentences way to differentiate protocol oriented programming from ordinary OO polymorphism?

  • finneycanhelp

    Nice article

  • Bikshapathi K

    Hi Natasha,
    It is Nice article. But I observed small bug in the above code. when we come to this screen, initially the switch is ON, If we made the switch OFF and scroll up till the row is invisible and the switch is ON. Here the datasource is not being maintained properly, It is always true in the above code.

  • Boris

    Hi Natasha, big fan of your blog. Shouldn’t

    switchToggle.on = delegate.switchOn


    switchToggle.on = delegate?.switchOn

    Also, what happens if the delegate is nil ? Does optional chaining default to false when encountering nil along the way in this call chain?

    • Boris

      Ah, never mind. Hadn’t noticed that delegate is not the property but is the passed argument (which isn’t of an optional type).

  • the best one

  • manwey

    Hi Natasha, I had an issue with yours first approach:

    I don´t know how to call the parameter onSwitchToggleHandler in the function configure inside tableView:cellForRowAtIndexPath

    What is the way to pass the Closure as a parameter?

    Thanks in advance

    import UIKit
    import XCPlayground

    class SwitchWithTextTableViewCell: UITableViewCell {
    var label: UILabel!
    var switchControl: UISwitch!

    typealias onSwitchTogglerHandlerType = (switchOn: Bool) -> Void

    private var onSwitchToggleHandler: onSwitchTogglerHandlerType?

    required init(coder aDecoder: NSCoder) {

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    let gap : CGFloat = 10
    let labelHeight: CGFloat = 30
    let labelWidth: CGFloat = 150
    let lineGap : CGFloat = 5
    let switchControlY : CGFloat = gap + labelHeight + lineGap

    label = UILabel()
    label.frame = CGRectMake(gap, gap, labelWidth, labelHeight)
    label.textColor = UIColor.blackColor()

    switchControl = UISwitch(frame:CGRectMake(gap, switchControlY, labelWidth, labelHeight))
    switchControl.onTintColor = UIColor.blackColor()
    accessoryView = switchControl

    func configure(
    title: String,
    titleFont: UIFont,
    titleColor: UIColor,
    switchOn: Bool,
    switchColor: UIColor = .purpleColor(),
    onSwitchToggleHandler: onSwitchTogglerHandlerType? = nil){

    label.text = title
    label.font = titleFont
    label.textColor = titleColor

    switchControl.on = switchOn
    switchControl.onTintColor = switchColor
    self.onSwitchToggleHandler = onSwitchToggleHandler
    switchControl.addTarget(self, action: #selector(SwitchWithTextTableViewCell.onSwitchToggle(_:)), forControlEvents: UIControlEvents.ValueChanged)

    func onSwitchToggle(sender: UISwitch) {
    onSwitchToggleHandler?(switchOn: sender.on)

    class TableViewController: UITableViewController {
    override func viewDidLoad() {
    self.tableView.registerClass(SwitchWithTextTableViewCell.self, forCellReuseIdentifier: “CellIdentifier”)

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(“CellIdentifier”, forIndexPath: indexPath) as! SwitchWithTextTableViewCell

    cell.configure(“Test”, titleFont: UIFont.systemFontOfSize(18.0), titleColor: UIColor.greenColor(), switchOn: false, switchColor: UIColor.redColor(), onSwitchToggleHandler:nil)
    return cell

    let tableViewController = TableViewController(style: UITableViewStyle.Plain)
    tableViewController.tableView.frame = CGRect(x: 0, y: 0, width: 300, height: 100)
    XCPlaygroundPage.currentPage.liveView = tableViewController.view

    • manwey

      I answered to my self:

      cell.configure(“Test”, titleFont: UIFont.systemFontOfSize(18.0), titleColor: UIColor.greenColor(), switchOn: false, switchColor: UIColor.redColor(), onSwitchToggleHandler:{[unowned self] (boolValue:Bool) in
      self.switchControlIsOn = boolValue



  • Rajesh

    Hello Natasha,
    Thanks for sharing.

    but one question: when cell.configure(withDataSource: viewModel, delegate: nil)

    When I pass nil in delegate, switch color is set to green, it hasn’t taken default purple color? why so?

  • VuTuan Tran

    can you explain: you are passing arguments of type ViewModel to configure method. However, in SwitchWithTextTableViewCell, the types are SwitchWithTextCellDataSource and SwitchWithTextCellDataSource