Let’s discuss MVVM for iOS

Photo credit: http://themetapicture.com/the-life-of-a-software-engineer/

As you progress as a software developer, you undergo specific stages.

First, you’re glad you’ve made contribution to the code. You go around telling people that you created that glossy red button. You’re also happy that your code works and doesn’t cause fire accidents.

​Then, you start writing code that you can actually read yourself a few weeks later.

And then, you write neater code, share it online, and work with other developers.

And finally, you write beautiful code. Code that reminds you of birds chirping in a lush green valley– code that is clean, testable and reusable.

Recently, I’ve been obsessed with writing simpler code. My first target was the ViewController. If you’ve developed apps for iOS, you’ll know that ViewControllers are easily the most bloated file in the project. It handles a lot more code than necessary — View Logic, Model Logic, View Layout, Web Service, Delegates etc.- the list goes on and this is too much already.


If you dig a little deeper, you’ll find that there is something wrong with the design pattern—MVC, “Massive View Controller” some call it. It’s a design pattern and a standard approach to building iOS apps. At its heart, it’s a very simple design and a good idea.

Here is the design –

In this design pattern, the controller separates the model from the view so that each can change independently. If we didn’t have such a decoupling, then every time the model changed, the view would need to change as well.

MVC almost work, however, as apps get larger, it is easy to wander off MVC, the controller gets bloated and it eventually becomes harder to test.


MVVM to the rescue

Let’s look at this alternative pattern, MVVM. It stands for Model-View-ViewModel and it comes from Microsoft. It’s quite similar to MVC, it formalizes the tightly coupled nature of the View and Controller and introduces a new component.

Wait, isn’t this MVC but reworded? Not really. There is a difference. The views still don’t hold references to Model, but neither do Controllers. Instead, there is a new component called ViewModel.

The ViewModel encapsulates data/properties that the view can bind to –it also encapsulates any validation logic and actions that can be performed. Typically, the ViewModel interacts with the model by invoking methods in the model classes. The ViewModel then provides data from the model in a form that the view can easily use. In this pattern we are essentially taking the state of our app and putting it into a ViewModel.


Photo credit: http://msdn.microsoft.com/en-us/library/hh821028.aspx

For the ViewModel to participate in two-way data binding with View, its properties must raise a PropertyDidChange notification, so that the View gets notified and can change its objects accordingly.


Benefits of MVVM

  • The ViewModel is an excellent place to put your validation logic for user input, view presentation logic, and network requests. As a result, the ViewController files become less bloated.
  • The View- ViewController component is completely isolated from the model. So during development, one developer can work on the UI part of the screen and another can take care of the logic for the screen, independently and concurrently.
  • It is easy to redesign the UI without messing with the model logic since they are both completely isolated. As long as you link appropriate properties to the ViewModel, you can swap view components in and out. This gives more freedom to experiment with the UI.
  • For Universal apps, both iPad and iPhone ViewControllers can interact with the same ViewModel.
  • It’s easier to test. Developers can create unit tests for ViewModel and model without the View.


Enough talk. Let’s get our hands dirty

Let’s see how we implement MVVM in code. We’re going to build a simple iOS app that fetches photos from Flickr.

Here’s the PhotosViewController

@interface RSPhotosViewController ()
@property (nonatomic, strong) RSPhotosViewModel *viewModel;
@property (weak, nonatomic) IBOutlet UICollectionView *photosCollectionView;

Notice that the ViewController owns the ViewModel instance. The ViewModel is nothing but a subclass of NSObject. It has only one photosArrayproperty. Here’s how its .h file looks like.

@interface RSPhotosViewModel : NSObject
@property (nonatomic, strong) NSMutableArray *photosArray;
– (void)updatePhotos;

The ViewModel.m file will handle fetching the images from Flickr.

To bind the properties of the ViewModel to the ViewController, I’m going to use KVO (Key-Value Observing).

But if you’ve ever used KVO, chances are that you’ve run into various kinds of issues. The API isn’t great and forgetting to remove an observer may result in memory leaks or—even worse—crashes. Thankfully, Facebook’s KVOController library solves these annoying issues with KVO.

So let’s set up the observers. The ViewController is going to observe changes to the photosArray property. Any changes to it, will reload thephotosCollectionView.


– (void)setupObservers
[_KVOController observe:self.viewModel keyPath:@”photosArray” options:NSKeyValueObservingOptionNew block:^(id observer, id object, NSDictionary *change) {
[self.photosCollectionView reloadData];


If you run the app now, you’ll notice that KVO still doesn’t trigger. The code[photosArray addObjectsFromArray:photos] won’t fire KVO yet. You have to use proxy for collections — mutableArrayValueForKey: .

From the NSKeyValueCoding Protocol Reference

Returns a mutable array proxy that provides read-write access to an ordered to-many relationship specified by a given key.

So your code should look like this:

[self fetchImagesCompletionBlock:^(NSArray *photos) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.photosArray removeAllObjects];
[[self mutableArrayValueForKeyPath:@”photosArray”] addObjectsFromArray:photos];
} failureBlock:^(NSError *error) {
NSLog(@”ERROR : %@”, error);


That’s it. Run your app, KVO will fire and voila–that’s MVVM for you.


And so…

Although there may be an increase in the amount of coding, the complexity has decreased significantly. Even if the amount of code increases a little, the benfits far outweigh the tradeoffs making this worth your while.

You can grab the complete code here.