January 21, 2016

Practical Software Architecture, Swift Style

The main software architecture pattern in iOS is model-view-controller (MVC), but when projects hit a certain level of complexity the fact that large amounts of code end up living in the ViewController layer in iOS can start to get ugly and hard to work with. This has lead to borrowing patterns from the model-view-viewmodel (MVVM) pattern in many projects at work.

In Objective-C this meant making heavy use of data bindings between the view- model and view layer, with RZDataBinding helping to take a lot of the rough edges off of data bindings. In most cases, this worked really well, and things like coalescing updates took care of many of the edge cases like notification storms or bad intermediate state being generated.

In Swift, there isn’t a clear win for data binding yet, so we’ve pulled back on the “bind everything” side of MVVM. One pattern that I’ve found useful is keeping view models as lightweight structs, having all of their internal values immutable, and generating a new view-model and replacing it on the view, which updates on didSet for view viewModel variable.

Overall, it’s leading to more thinner layers in an app, because it means the viewModel doesn’t contain any intelligence about self updating, which moves the self updating logic into the viewController, or into a services layer object that that produces a model object, which then can be parsed into the appropriate view-model.