iOS architecture: Idiomatic swift MVC design pattern

Maksim Vialykh
3 min readMay 26, 2018

--

Hello, dear reader. Today I introduce my own vision of MVC pattern that can be useful as balanced solution between development speed, responsibilities and testability.

MVC Design Pattern

What we have:

Model — object that works with data. Model must conform to ModelInput protocol. It works with storages (local — for example CoreData, remote — for example REST API service) and provides plain objects (just structures) to the output.

Controller — ViewController object that has strategy “logic how to navigate and render data”. It must conform to ModelOutput protocol that describes functions with updates from Model and ControllerInput protocol.

View — All kinds of UIView. It can be just UILabel or UICollectionView. View must only render plain objects and notify controller about interactions.

How it look in project:

Let’s look at each component code, but first — how it looks in project structure.

MVC module in project

ModelInput — protocol that describes what properties model which we must have in our module. For example controller need card plain object and function to upload image. We want use independent model, not just concrete class.

Model Input

ModelOutput — protocol that provides instructions for controller. For example model will provide updates about task. We will provide implementation in controller class later.

Model Output

Model — class that conforms to ModelInput protocol and has a weak reference to output. In our case model have a card variable and function to upload image data.

Note: Using protocol abstractions provide possibility to do injections (will demonstrate in configuration class and make out layers more testable)

Model

ControllerInput — in our case we should have an abstraction interface to use weak reference of controller in CollectionViewDataSource (actions from UIView). That protocol describes functions for our controller instance.

Controller Input

Controller — have a strategy how to work with model and render plain objects on view. For example: when user taps to “start” button view: UICollectionViewCell class instance communicates with controller over ControllerInput protocol and it calls “startTask” function. Now that function is just for test, but in future we will implement model to retrive data about task, setup view to show activity and etc.

View Controller

View — in our case it is UICollectionView class instance. But where is data source you should ask me. Yep, it is part of iOS design pattern. Data source moved out from controller to the separated class TaskListCollectionViewDataSource. It’s a part of UI because data source just provides plain objects and create UIView instances with rendered plain object data.

Ok, we’re done. But I think you still have a one question. How to inject layers between them?

Configurator — object with one function. Inject layers between them.

Configurator

Configurator can be used in prepare(for segue:) funcion. But it’s uncomfortable to use it in each controller. One small but pleasure class is

Initializer — just add object to your viewcontroller in storyboard, set object custom class and setup reference to viewcontroller instance and you’ll never think about module configuration.

custom object class
initializer viewController reference
Initializer

You’ve done it!

Remember, the receipt to success is continuous learning and communication with colleagues including, self-education.

This was a small guide about iOS swift MVC architecture design pattern. Read more on Apple Developer site. Don’t stop self-education.

In next stories we’ll discover how to write tests for that architecture.

Subscribe to my account to get notifications about new stories.

If you still have questions — write about it in the comments. I’ll answer them in future articles.

--

--