Creating light view controllers is a sure way to grow popular among iOS folks. The easiest way to do that is to pull everything out that is not an original concern of a view controller (or at least shouldn’t be).

Most of us have been doing this for some times when it comes to views, which shouldn’t ever be layed out or configured except for some value input. Most of us also extracted model manipulation to some kind of model layer, be it a view model or some different entity juggling your data.

Soroush Khanlou came up with a great post on how to extract reusable functionality from view controllers. His idea is to basically create (visible or invisible) view controllers, each of which encapsulates a narrow set of functionalities and add them to a view controller using some convenience calls added using an UIViewController-Extension. I like that.

One aspect remains unsolved, and this is the one I hate the most: when we’re talking about Loading Views, Empty State displays and “You are offline”-Views, the complicated thing is not displaying these things – I think that’s pretty straightforward. I hate having to observe a plethora of different values and keeping track of when and where I’m exactly doing things. My ideal call would be:

self.addBehaviour(EmptyStateBehaviour(), when: "isEmpty", on: viewModel)

Turns out that building the infrastructure required to make that a reality is rather trivial. I’ve just created a View Controller extension that adds behaviour handling. I’m using PMKVObserver to save myself some KVO-headaches, as well as SnapKit to easily create constraints.

import UIKit
import PMKVObserver
import SnapKit

extension UIViewController {
    func addBehaviour(behaviour: Behaviour, when: String, on: NSObject) -> Void {
        _ = KVObserver(object: on, keyPath: when, options: [.New]) { _, change, _ in
            let new = as? Bool
            if (new != nil && new!){
                // install behaviour
                if (behaviour.view().superview != self.view){
                    self.view.insertSubview(behaviour.view(), atIndex: 1000)
                    behaviour.view().snp_makeConstraints(closure: { (make) -> Void in
            } else {
        // Called to make sure the behaviour handles the current state immediately.
        on.setValue(on.valueForKey(when), forKey: when)

A behaviour is just a simple wrapper around a view. I’ll add some lifecycle methods (willInstall, didInstall) at some point, so here’s your reason why this is a seperate entity around a simple UIView.

class Behaviour: NSObject {
    func view() -> UIView {
        return UIView()

class EmptyStateBehaviour : Behaviour {
    let internalView = UIView()
    override func view() -> UIView {
        internalView.backgroundColor = UIColor.redColor()
        return internalView;

I like that – I can easily “bind” to a property and the behaviour automatically adds or removes itself.

One note though, if you’re wondering why it’s not working, double-check that the variable you’re subscribing to is marked as dynamic.

class ViewModel {
    dynamic var isEmpty = true