With the release of Ash Furrow’s new book on Functional Reactive Programming in iOS, I’ve seen a lot of debate about whether or not this whole paradigm shift is a good idea. Why do it? Isn’t what Apple provides with their specific flavor of Model-View-Controller sufficient? What the heck is Model-View-ViewModel?
OMG! The acronyms! It burns us!1
That’s what leads me to this post. I would like to build a bridge that stretches across the divide between the traditional way to build iOS applications and the strange new world with MVVM, Reactive Cocoa, RXCollections and the like.
First off, you are not stupid if you have trouble groking the README and documentation of Reactive Cocoa. It’s a very different paradigm than what grew up around Objective-C. It’s a clever abuse of the C preprocessor—a layer on top of Objective-C, which itself is a layer on top of C, etc.
All this extra syntax makes it hard to just jump in and read the code. It helps to know how and why the syntaxes grow into what they are today. After all, we’re quite forgiving when it comes to the block syntax Apple gave to us, right? Right?!?!
The hacked and layered nature of things like Reactive Cocoa have downsides, for sure. But I’m excited to see experiments giving us new primitives with which to compose our application logic. And it’s not just academic. Github is behind Reactive Cocoa and applies it to real world problems in their Mac and iOS applications.
So, back to view-models.
Think about what a table view data source does in your application.
It’s not your “model” layer in a classic MVC sense. Your models might be, say,
NSManagedObjects as part of a Core Data store. These models have validation
rules, transformed properties, and relationships that construct what the core
of the application does.
A table view data source is none of these things. It’s purely a layer between the table view and the model. The model defines lists of things, but the table view data source transform those lists into sections and rows. It also returns the actual table view cells, but that’s not what I’m focusing on here. The key is its role as a middle-tier data transformer.
By default, because of Apple’s templates and documentation, we typically use table view controllers as the data source. There’s nothing wrong with that in itself, but it can lead to very large view controllers that both manage representations of screen state (navigation, transitions, and so forth) and feed data to the table views.
I’ve found great success creating separate
NSObjects that implement the
UITableViewDataSource protocol and dedicating those as data sources of table
views. We end up with more focused objects, they’re simpler to test, and it
leads us this realization…
We’ve just made a bunch of view-models!
Yes, the people who work with MVVM all the time will rightly criticize that statement. I’m overgeneralizing a bit, but bear with me. My point is that the table view data source is a “model” layer between the actual list of data and the table view that displays it.
I bring this up to show that the core of MVVM isn’t as foreign a concept on iOS as it seems. If you read Ash’s book, you’ll get a heavy dose of all the other things that MVVM brings with it, but you can at least get a head start in your understanding by thinking of the way the data source sits as a transforming layer between your model and your view.
Imagine this same mechanism generalized to other areas. Instead of bogging down
NSManagedObject subclasses with extra methods to display data in
different formats, you build intermediate view-model objects that your views
could consume and watch. If you update a primitive integer on your model, the
view-model sees that change and updates the formatted
representation. And the view sees that change and updates the text label on
Next, imagine you had some sort of syntax to describe the bindings between the model, the view-model, and the view. If you’re still tracking with me then you’re ready to take a look at things like Reactive Cocoa. It’s a syntax built on top of Objective-C through which you bind subscribers to producers of events. It’s like KVO but with broader implications.
I hope this helps a bit if you’ve been curious about the Reactive Cocoa craze on iOS. I don’t think it’s above critique, but don’t write it off just because it isn’t the traditional way. We need more experiments like this that help us describe problems with primitive structures.
Count me in.
You know, if we wanted to order the acronym based on the flow of data it would be Model-ViewModel-View…but that’s just cruel.↩