When you decide to jump into iOS development, you are exposed to a new language, new APIs, frameworks, new conventions. And no less you are exposed to a new architecture design pattern, Apple’s Model View Controller or MVC (recommended by Apple itself).
Before jumping to Apple’s MVC, let’s stop and talk a little bit about Classic MVC. MVC has been traditionally used by popular programming languages like Java, Python, Ruby etcetera, mainly for GUI programs.
MVC (Model View Controller)
As you can see from the diagram, the model is responsible for managing the data of the application. It’s the application’s dynamic data structure and the central component of the pattern, while view presents the model in some kind of format e.g chart, list, diagram, etc.
The controller after validating the received user input performs interactions by converting that input to commands for the model or view.
You can ask if it is possible to develop an app using this pattern? YES, but you wouldn’t go for it for many reasons. The problem is that with this pattern we are not guaranteed of having a decoupled code. All three entities are exposed to each other, thus IT WILL NOT HELP us solve the code reuse or no-flexibility problem either.
What about Apple’s MVC?
Apple’s MVC is all about communication between 3 entities (the same ones mentioned above) and they have to obey certain rules during communication. The controller is the center of all the communication. Its job is to format the model’s information for the view and to interpret the user’s interaction for the Model. Since the Model is UI independent, one of the most important rules of MVC communication is that Model and View should not talk to each other.
View is the Controllers minions since we mentioned that Controller the center of communication and View cannot talk to Model the other way round. The question is whether View can talk to Controller?
Yes, it can. Although, since the View doesn’t own the data they display, the communication must be blind. For example, collectionView or some other generic view is showing you a huge collection of books. Let’s say there are 100K books, its foolishness to have that generic view to bring all the books. So the alternative is to use a protocol mechanism to call a set of predefined methods like numberOfItemsInSection, cellForItem, etc. This way View requires the Controller to provide the Model’s data and display it, as we mentioned above.
But what about the Model, can it talk to the Controller? Well, we mentioned above that the Model is UI Independent. Since the Controller is essentially UI dependent, the communication can’t be direct. In case some Model’s data changes and it wants any UIs that are interested to update, we can use Notification and KVO (Key-Value Observing) for that scenario.
To give you a better overview, here is a diagram from a Stanford professor, Paul Hegarty.
It looks very plain right? But things can get a little bit more knotty.
Things are quiet in control when we have a really simple ViewController which only handles events and manages/layouts views. What about when on top of those mentioned above, you also need to do the following:
- Error handling
- Model encode/decode
Well, in that situation you can put every task mentioned above, on the ViewController. After a short-while start complaining about how MVC stands for “Massive View Controllers”. OR just stop complaining and examine which tasks are not necessary ViewController’s responsibility!
Which one of those jobs can be moved out of the ViewController?
Actually, almost all of them can be moved out of the ViewController, let's take some examples.
Pushing new ViewControllers isn’t necessarily done by a ViewController, instead, you can use Coordinator Pattern:
Using the coordinator pattern in iOS apps lets us remove the job of app navigation from our view controllers, helping make them more manageable and more reusable, while also letting us adjust our app’s flow whenever we need. (read more…)
Another task that can be removed from our view controller is Layout. Well, what you can do in this case is that you can just create a custom view and on loadView() method, assign that custom view to sefl.view:
Networking + error handling, encoding/decoding & caching
Creating a separate class which covers the networking tasks is a much better way than doing it inside ViewController, as you can see in the example below:
ViewController calls the fetchData method with completion callback from ApiService class. The cool thing is that you can also do error handling, encoding/decoding and caching on this class (ApiService). This way we avoid our ViewControllers from being “Massive”.
In any way, I am not putting one architecture design pattern above the other. This article aims to clarify some misconception concerning MVC, where some developers intent to put all the logic on ViewControllers, something you can’t find on Apple’s Documentation as a suggestion.
Architectures are not here to solve our problems, they help us to do so. Each design pattern architecture has its pros and cons. And each one of them is destined to tackle a certain situation, so use them wisely.
Found this article useful? Follow me (Besar) on Medium!