Skinnier Controllers Using View Categories

Brent Simmons explains in a recent post how not to skip the C in MVC when binding model objects to views like UITableViewCell. While I agree with everything in his post, I am also of the opinion that controllers should be kept as skinny as possible. This simply because view controller code is the least reusable code in any iOS project.

Therefore, I thought I would share how I deal with binding models to views without breaking the MVC pattern. I originally picked it up from the book iOS 5 Programming Pushing the Limits by Mugunth Kumar and it is quite simple; encapsulate the code that maps the model properties to the view elements in a category on the view class, and use that from the controller. This makes the mapping code re-usable, while only adding a single line to your controller code in cellForRowAtIndexPath:.

So, say we have a model object Forecast and a UITableViewCell subclass named ForecastCell. In this case, I would have a category ForecastCell+Forecast with a single method updateWithForecast:(Forecast *)forecast. This method takes care of reading out the model property values and populating the view elements such as labels or image views.

This makes updateWithForecast: the only method call needed in the controller code. Almost. If you need to configure the cell based on an indexPath (e.g. setting a view tag), then do so in the view controller and not in the mapping category. The indexPath juggling is the concern of the UITableView and its controller, not the model nor the cell view.

The main benefits of this approach are:

  • It adds a minimal amount of code to your view controllers.
  • The mapping categories can be reused across multiple view controllers dealing with the same type of model and views.
  • A view can be updated using multiple model classes. Just create a seperate category on the view for each model object. In the above example that could mean adding another category ForecastCell+SomeOtherModelObject in addition to ForecastCell+Forecast.
  • A category is way easier to unit test than view controller code (thanks to Ash Furrow for pointing this out).

This is a simple approach, but I thought it might be worth sharing.

On the topic of skinny view controllers, Chris Eidhof also has some good tips.