Understanding Model-View-Controller (MVC)
Developing any type of software requires logical thinking and strong problem-solving skills. However, programmers have been building software for decades, and have collectively encountered and solved a great number of the common problems encountered when writing code.
As time has passed, some of the best solutions to common problems that have been developed and shared are in the form of patterns. On a granular level, there are design patterns that are used to solve common problems at the object or multi-object level. As an example, the Singleton pattern describes a class that may only have one instance, with a global access point. Since it isn't a specific set of instructions for any given language (remember, it's just a pattern), the Singleton pattern can be implemented in many different languages, as is the case with most design patterns.
In addition to solving smaller issues with design patterns, programmers have also developed many patterns concerned with outlining how an entire program should be structured; these are called architectural patterns. At the core of Cocoa Touch, Apple's native API for building apps for iOS, is the architectural pattern called Model-View-Controller.
The pattern is pretty simple to understand: the code of an MVC program is separated into a data layer (the model), a user presentation layer (the view), and a third layer that connects the two halves (the controller). This allows for a very logical separation of functionality in your code.
Note
Cocoa Touch is based on the original Cocoa, which is the API that Apple built for programming OSX apps. There is a very fascinating history behind Smalltalk, Objective-C, NeXTSTEP, and how all of that led to OSX and ultimately iOS. Since it won't be covered in this book, I hope you will research and understand these technologies that led to the modern iOS development environment.
Since it is foundational to the underlying technology of Apple's development frameworks, using MVC when building your applications is pretty much mandatory, and enforced at every turn. As we explore Xcode and Swift, you'll see the idea of MVC everywhere: CoreData is how you can design your model; Storyboards are quite literally where you create views; UIKit has many types of built in view controllers. In time, we'll cover all of these individually and in depth, but for now let's make sure we have a firm grasp on the basics of Model-View-Controller.
At the very core of an application is its data. In a music app, that would be the music files and associated metadata. In a contacts app, it would be a database of your saved contacts. In Twitter, it's the tweets. You get the idea. The model of an application is all about how you represent and manipulate that persistent data.
Let's use the contacts app as an example, and assume that the database of contacts is stored locally on your device. The model for that data would need to do several things. There needs to be a way to load contact information from the database into an object in code. There should also be ways to modify and save that data, for times when a user might want to change a contact's information, or add a new contact altogether. Finally, the model needs to be able to tell a controller when any of the contact data has changed:
While the first capability (having a container to load data into) is an internal feature of the model, the other two capabilities are essential exposures needed for the model to communicate with the controller. The controller will be capable of sending updated information to the model, which needs to be able to receive that data, format it correctly, and save it back to the database. Likewise, the model needs to let the controller know when its data has changed, so that the controller can react accordingly.
This creates a clean, separated relationship; the controller sends simple data to the model and handles general update events, while the model takes care of all the saving, loading, manipulation, and formatting.
While the model is taking care of the raw data, the view is in charge of what is actually being seen by the user. Continuing the example of a contact management app, let's take a look at how the view might be handled:
Here, we can see that the view is showing the user some nicely formatted contacts. On the left is a round portrait of the person, followed by their name, and less important on the right is a greyed out word that signifies if the contact is for that person's home or work information. You can also see that the controller is sending the view the information to display, and that the view is relaying any user input back to the controller.
What's powerful about decoupling your view from all of the other application logic is that you can rapidly iterate how your app looks and feels, without having to worry about breaking any of the important logic underneath. It also keeps the amount of data needed in your model to a minimum. For example, our model has no idea that the portrait image will be cropped to a circle, or what size the font needs to be on a contact's name. The view keeps track of everything related to presentation, often in a way that is highly reusable.
We've seen how the controller works independently with both the model and the view and we've got a pretty good idea of how everything works together, but let's look at a little bit more of a detailed big picture to really see what the controller is doing:
Looking inside the controller, you can see that we've elaborated a bit on what's going on. You'll notice that the controller is capable of receiving notifications from both the model and the view, and then make decisions based on those notifications. It is also capable of sending updated information back to the model and the view.
Note
As you'll see later in the book, a controller can (and often does) do a lot more than just listen for changes. It is also responsible for setup tasks, supplementary logic, and pretty much anything else that doesn't fit in the model or view.
This cycle repeats for the duration of the controller's existence. Listen for changes. Process notifications. Update appropriate objects. Listen for changes. Process notifications. Update appropriate objects. It's a very elegant solution that keeps your code decoupled while still making it easy for changes on both sides to be properly dealt with throughout the application.
However, this diagram shows a very generic representation of controller logic. Often when developing an app, you'll write many unique controllers that all need custom logic, and each handle things a little differently. At each controller's core though, you'll find that they all need to implement this functionality in some way.
Now, we've spent some quality time with the theory of the Model-View-Controller software architectural pattern, but I find the best way to learn is through examples. So let's take a quick look at how MVC is used on an Internet browser, something most people use every single day:
One of the most interesting parts of how the web works is that it has several different languages, and each one handles a different function. HTML is a markup language that defines the content of a web page. This means that HTML defines our model. There usually shouldn't be any formatting in an HTML file, so viewing one directly will be an unformatted jumble of source text and images. In Figure 1.9, you can see how the HTML document contains the data for the website title, along with images and captions:
Separate from HTML is a style sheet language called CSS. CSS knows nothing about the data in your HTML files, and is only responsible for defining the visual rules for how HTML elements will be displayed. It determines things like the height and widths of different elements, color information, and rules for how text should be displayed. This would make CSS in charge of our view. In Figure 1.10, you can see how the CSS file results in a basic layout of a web page, such as position and size information. However, all of the content is blank, to reinforce that it does not know anything about the content that will be displayed:
Finally, we have the browser itself, which loads both the HTML data and the CSS rules to give us the final rendered page. The browser uses a third language, JavaScript, to dictate its behavior. It can receive input events like clicks and key-presses, and listens for changes in the model. It can then respond to these events with JavaScript callbacks. Our browser is our controller.
Note
If you're well versed in coding the web, you'll know that there is a lot more than this going on behind the scenes. There are many other languages and technologies that keep the modern web afloat, but we're simplifying it for educational purposes.
Hopefully, looking at MVC through a piece of software you are already familiar with has given you a stronger grasp of these concepts, in addition to giving you a bit of insight into how the web works! Now let's jump back to iOS and put everything together.
As I alluded to earlier, Xcode and the entire iOS toolset and APIs are built around the concepts of Model-View-Controller. I'd like to point out a few of the more obvious ways in which the concepts are enforced, but as you read through the book and eventually go out to explore and learn on your own, keep an eye out for all of the ways that MVC is present:
As we've been doing, let's start with the model. Usually when working on an iOS application, your goal is to represent some kind of data. Sometimes it is a small amount of simple data, like in a weather application, and you can just retrieve it from the web on demand each time you load the app. Other times, you'll be storing and processing large amounts of data, usually in some type of database.
The simple cases don't require too much thought, but there are some great features in Swift that we'll cover in Chapter 3, Introduction to Swift 3, that make simple models easy to code, and easy to use.
For the more complex scenarios, there is CoreData, which is essentially an Apple-developed solution for building data models. CoreData is built into iOS, and a visual CoreData model editor is built right into Xcode (see Figure 1.12). This means that implementing a complex data model is fast, easy, and native to the development environment. We'll talk more about CoreData in Chapter 9, Working with Core Data:
Next, let's talk about views. When we talked about a web browser in the last example, we looked at how CSS dictates the appearance of a web page. On iOS, there's an even better way to build out our visual layouts: Interface Builder (see Figure 1.13). As the name implies, Interface Builder allows us to directly drag and drop UI elements in a visual What-You-See-Is-What-You-Get (WYSIWYG) editor. We can move things around, set different properties, and then even set constraints that allow us to dictate how they should look when the screen changes orientation, or when displayed on different screen sizes. This means that building views is done in a way that makes the most sense: visually. We'll be covering Interface Builder in Chapter 4, Using Storyboards, Auto Layout, and Size Classes.
So now we've discussed how to build models and views for iOS apps, and we haven't even talked about coding yet! That's a bit of a lie though, since there is a little more programming than was mentioned in the model section, but still! If we think about how MVC works, though, this should make sense. Models and views are mostly things that need to be defined; all of the action happens in the controller.
On iOS, controllers are usually implemented by creating a sub-class of a UIViewController, a class built into the UIKit framework. We could talk about UIViewControllers for hours (and in fact, we will throughout the rest of the book), so for now just know that this is where you will be doing a good chunk of your coding: handling input events, updating the views, and running supplementary logic.