How to Use MVC
MVC is not a difficult concept, but there are two main reasons for emphasizing its importance in iOS:
- MVC is used by CocoaTouch (and Cocoa on OS X). If you adhere to the same paradigm as the frameworks used for writing all iOS applications, your code will flow well and not clash with the built-in classes, including UICollectionView.
- MVC is generally a good framework, and using it will help you make well-written, maintainable apps.
Now that you know why MVC is important, it’s time to look at what MVC is. Figure 1.1 shows the basics of MVC; strong relationships are represented with solid lines, and weak relationships are represented by dashed ones. Strong and weak relationships indicate to the compiler how to manage memory and are important to avoid memory leaks, which would eventually lead to the app being terminated.
Figure 1.1. Basics of MVC
At the heart of MVC is the controller object. The controller is a View Controller—as in UIViewController—and it controls the view. It maintains a strong relationship to this view, which is what is presented to the user on the screen. The controller also maintains a strong relationship to the model. The model represents data that is represented in the view.
If your view ever has a reference to your model, or vice versa, you’re doing it wrong. This book uses MVC and you should, too.
Most of the code in any given application resides in the controller; controllers mediate the interactions between views and models, which is why the code in controllers is often referred to as “glue code.”
What sort of interactions does a controller mediate? Well, if the view contains a button, then the view controller is notified when the user taps that button. Typically, user interactions trigger actions to modify, create, or delete models belonging to the controller. The controller receives the user interaction from the view, updates the model, and then updates the view to reflect the changes made to the model.
Sometimes, the model changes without user interaction. For example, consider a view that displays a large JPEG, which is being downloaded. When the download completes, the controller should be notified so it can update the view. On iOS, you have a few different choices for how to notify the controller. My favorite is Key-Value Observation (KVO). Controllers can register themselves as observers on model objects so they are notified whenever the model’s properties are changed. Other ways for models to interact with controllers on iOS include NSNotificationCenter, delegation, and NSFetchedResultsController. I would eschew NSNotificationCenter for model-controller interaction in favor of NSFetchedResultsController or KVO. Although this book doesn’t discuss Core Data, UICollectionView works very well with NSFetchedResultsController in a similar way to UITableViewController.
This last example demonstrates a gaping hole in MVC: Where does the network code go? As a responsible iOS developer, you should keep the view controller to only mediating the interactions between the view and the model. If that’s the case, then it shouldn’t be used to house the network access code. As discussed in Chapter 6, “Adding Interactivity to UICollectionView,” the network code should be placed outside of the typical MVC pyramid. Network access should not involve the view whatsoever, but it can sometimes involve the model.
Well, that’s mostly true. In fact, a common paradigm for fetching details about a model from an application programming interface (API) involves Grand Central Dispatch blocks. A block lets developers treat anonymous functions as first-class Objective-C objects. These blocks can be invoked later. Controllers can start a network request and pass the network-fetching object a callback block that updates the view. Technically, the network code has an indirect reference to the view, but you ignore it lest you find yourself falling down a rabbit hole of pedantry.
If you are experienced in iOS development, all of this should sound familiar. UICollectionView and UICollectionViewController don’t exist in silos; they are used within applications with models and with the rest of CocoaTouch. It would be irresponsible to present them in any other context than that of MVC.