LooLocator: Writing an MVVM App using Swift
Model-View-Controller (MVC)1 is the defacto Apple prescribed approach to create iOS apps. After developing apps for a while, the shortcomings of MVC become obvious, earning them the nickname Massive View Controllers among the developer community. Some of the problems with MVC are:
- Poor testability: ViewControllers end up doing so many things and it makes testing cumbersome.
- No well defined way to put networking code in canonical MVC, so ViewControllers end up doing that part.
- Controllers by definition aggregate many related/unrelated responsibilities, which makes maintenance a nightmare.
To counter this, several design patterns for iOS have emerged (VIPER, MVP, Clean etc) and my favorite among them is MVVM. 2
In this series of posts, I’ll document my journey in implmenting a simple iOS app using MVVM pattern.
Problem statement:
“Write an app that gets available ameneties (like toilets) within walking distance of the user, from OpenStreetMap.”
This will serve as a nice example of designing a decoupled and tested architecture, as it has:
- Platform specific componenets (MapKit)
- Network operations (REST call to OpenStreetMaps)
- Views and ViewModels.
- Potential enhancement to implement caching of data.
The final project (with unit tests) can be found at my Github
Step 0: Bootstraping the project
We’ll use the standard Single View App template to create the project.
After creating the Single View App, we will add a Cartfile
to manage dependencies of the project using Carthage. Carthage is a minimal, and decentralised package manager that doesn’t hijack the project configuration like Cocoapods. The Cartfile looks like this:
github "Quick/Quick"
github "Quick/Nimble"
github "AliSoftware/OHHTTPStubs"
The project will be a Single View App, and it uses the following frameworks to make things easier for development:
- OHHTTPStubs To Mock Network calls for unit tests. This is added to the test target section of the
Cartfile
- Quick/Nimble: Tools for writing Behaviour tests for our components. These are added to the test target section of the
Cartfile
As we can see the main App has no 3rd party dependencies, and all the Carthage dependencies are for the Test Target. The test target will be a non-hosted test. 3
#### Organization Let's start breaking down the requirements into tangible parts. Looking at the problem statement, the app has 3 distinct responsibilites, viz.
- Get the current location
- Get the Amenities in range from OSM
- Show the Amenities on the map
Based on this information, we’ll explore the creation of the iOS app in the following stages:
- Defining the Model
- Creating a modular and testable location component
- Creating a modular and testable networking layer
- Define the ViewModel
- Implement the ViewController to bring it all together.
In the next post we’ll start with defining the Model classes.
-
MVVM originated at Microsoft, and there’s a nice explanation on ObjC.io about MVVM pattern. ↩︎
-
Non hosted test targets are independent of the App Target, and are better suited for testing modular components. A more succint explaination can be found here: A tricky case with Application Tests ↩︎