Lecture Handout
Last updated
Last updated
When building an iOS application, we need someway to move between different views. Otherwise, we would just be staring at the same screen the whole time and that would not provide great user experience. So, how do we create a multi-view application? The answer is navigation (Note: When we talk about navigation, we are talking about transitioning from one view controller to another). Specifically, there are two forms of navigation, pushing/popping and presenting/dismissing.
Before we can discuss pushing/popping view controllers, we need to make sure we understand another concept, UINavigationController. From Apple’s documentation, “A navigation controller is a container view controller that manages one or more child view controllers in a navigation interface. In this type of interface, only one child view controller is visible at a time.” In other words, a UINavigationController can be thought of as a stack that manages multiple view controllers. However, only one is ever present on the screen at a time.
Using navigation controllers, we can accomplish the first form of navigation, pushing/ popping. What does this form of navigation look like? Lets take a look:
If you go into your Settings application and then click on Wi-Fi, the transition from the Settings screen to the Wi-Fi screen is the pushing navigation. Thinking about this in terms of the navigation controller’s stack of view controllers, the act of pushing is equivalent to pushing that view controller onto the top of the stack so that the view controller is now the only visible view controller on your screen. Now that you are on the Wi-Fi screen, if you were to press the < Settings button on the top left, you will be brought back to the Settings screen. This transition is the popping navigation. Similarly, the act of popping is equivalent to popping the top view controller from the stack so that another view controller is visible. Their code equivalents are:
Unlike pushing/popping, in order to present/dismiss a view controller, we do not need to have a UINavigationController, and thus no stack. When we present a view controller, all we are doing is presenting a view controller directly on top of the current view controller. What does this look like? Lets take a look:
If you open the Ithaca Transit application on your phone and then click the (i) icon on the top right, the About Us view controller gradually comes up from the bottom of the screen. This transition is the presenting navigation. Similarly, if you press the Done button on the top right, you will see that the About Us screen will gradually go towards the bottom of the screen until it disappears. This transition is the dismissing navigation. Their code equivalents are:
What is MVC and why is it important? MVC is a type of software design pattern. In other words, it is a set of rules regarding code architecture that we follow when writing code. MVC stands for Model-View-Controller and it is the software design pattern that we will be using when developing iOS applications. Before we explain the idea between MVC, let us break down the components.
Models refer to objects that represent the data for our application. For example, if we were making a Music Player application, a model object that we would have is a Song. Or if we were making a Social Network application, a model object that we would have is a User. These model objects usually experience change as the user interacts with our application. For example, a user might change their username, updating the User object, or a user might "like" a song, updating the Song object.
Views refer to the actual interface components that we use to build our application and that users mainly interact with. For example, this includes UIButton, UILabel, UITextField, etc. Essentially, views are just the UI part of our application.
The controller’s main goal is to act as an interface between the model and view. The controller’s job is to process any of the logic needed to update the views, which may include server responses that the client receives, or simple computations based on the user's tap location. The controller then updates the model objects accordingly and, as necessary, update the view.
Putting this all together, MVC can be summarized into a couple of steps. Any user interaction with our view gets notified to the controller which in turn can lead to an update of our views or model objects. Similarly, any change in our model objects (perhaps through a server request/response) gets notified to the controller which can in turn lead to an update of our views or model objects. The most important feature to keep in mind about MVC is that the model and view components should be independent of each other. Both of these should communicate with each other only through the controller.
An example of this flow is an application might have a user settings page, which will show information about the user, including name, username, and contact information. The view might include UILabels that display the user's information but the information is actually stored inside of the User object, which has name, username, and contact fields. When a user performs an action, such as editing their username, the view will notifiy the controller, which will update the username field of the user model. The controller will then be notified of this change in the model, which will in turn update the view that is displayed. At the end of this user interaction, the user settings page will be updated with the user's new username.
Delegation is used to allow child objects to communicate with its parent without having to know the exact type of its parent. In iOS programming, this is useful when we want our child view controller to communicate with its parent view controller or when we want our tableview cell to communicate with the parent tableview in response to some event. In other words, delegation is just a way for one class to give responsibility to another class.
How do we implement delegation in Swift? The answer are protocols. According to Apple,
“A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.”
In other words, you can think of protocols as being similar to interfaces in Java. It is just a set of methods and/or properties that any class that conforms to it needs to implement. Lets take a look at an example:
To declare a protocol, we simply have to preface the name of our protocol with the protocol keyword. Inside the block, we then define the set of methods and properties that we want any class that conforms to this protocol to implement. Thus, if ViewControllerB
conforms to ViewControllerDelegate
, ViewControllerB
must define some value for a variable called someVariable
and also have a method whose name is viewControllerDidReceiveSomeEvent()
.
One good way to wrap your head around delegation and protocols is to take a real life example. Let's say that we were in a restaurant. This restaurant has a chef, a waiter, and a menu. In this case, the menu is our protocol. Why? The menu contains a list of dishes that some one must be able to make. Similarly, the waiter is the delegator. The waiter’s job is just to receive the orders of customers but they cannot themselves make the dishes, they need someone else who can. Lastly, the chef is the delegate because they are the one who can make the dishes on the menu when asked by the waiter.