DEV Community

Fernando Martín Ortiz
Fernando Martín Ortiz

Posted on • Edited on

Introduction to the Controller

Note: This article is part of the course Introduction to iOS using UIKit I've given many times in the past. The course was originally in Spanish, and I decided to release it in English so more people can read it and hopefully it will help them.

Views in UIKit

Views in UIKit inherit from the base class UIView. There are specialized type of views, such a buttons, sliders, lists, grids, etc. We can use UIView as it is, or subclass it, or use its subclasses.

UILabel

It's a text label.

Some of its more frequently used members:

  • text: String - it defines the text the label shows.
  • textColor: UIColor - it defines the text color of the label.
  • font: UIFont - it defines the font the label uses.

UIButton

It's a button with a text label on it. We can customize its behavior when it's clicked (more on this later).

Some of its more frequently used members:

  • setTitle(_:for:) - modifies the text inside the button label.
  • setTitleColor(_:for:) - modifies the text color of the button label.

For both of them, in the for param, let's use .normal.

UIImageView

It's a view with a image on it.

Some of its more frequently used members:

  • image: UIImage - defines the image the view is showing.
  • contentMode: ContentMode - defines the way the image will fit into this view in case their sizes aren't equal.

Most used values of ContentMode:

  • ContentMode.scaleToFit
    image

  • ContentMode.scaleToFill
    image

  • ContentMode.scaleAspectFit
    image

UITextField

It's a view that shows an editable one-line text.

Some of its more frequently used members:

  • text: String - defines the text the textField shows.
  • textColor: UIColor - defines the textField text color.
  • keyboardType: UIKeyboardType - defines the keyboard type that will be displayed while interacting with the text field.
  • isSecureTextEntry: Bool - defines whether to show or not the text field as a password field with dots instead of characters.

UIStackView

It's a view that displays other views inside of it.

  • It allow us to sort view in vertical or horizontal axis.
  • A stackView doesn't require constraints for its subviews, although it needs constraints to display itself inside its container.

UIViewController life cycle

What is a life cycle?

A lifecycle is the set of states that define an object from its creation to its destruction.

In case of a controller or view, we aren't allows to modify its life cycle state, but we can react to those changes, and customize what happens when a view or a controller changes its state.

Whenever an object changes its state, a life cycle method (or simply called hook) is executed. We can override any of those methods to customize what will happen in such a case.

image

The diagram above shows the different methods in the view controller life cycle and the possible transitions between them.

For this course, we'll just see the most important states and transitions.

  • init: it's executed when a controller is instantiated. In this moment, we don't have the view loaded in memory yet. If we want to access an element in the view at this point, the app will crash. Be careful.
  • viewDidLoad: Once the view in the controller has been loaded into memory, this method will be executed. It will happen once in the entire controller's life cycle.
  • viewWillAppear: Once the view in the controller is shown to the user, this method will be executed. It can happen any number of times during the controller's life cycle.
  • viewDidAppear: This will be executed once the view is already shown in screen. If the app navigates to another view using an animated transition, this method will be executed once the transition has finished animating. In this moment, the views has actual values for its constraints.
  • viewWillDisappear/viewDidDisappear: They are like viewWillAppear and viewDidAppear but in the opposite direction.

@IBOutlet and @IBAction

A controller has two responsibilities:

  • To send the data from the model to the view: This can be done by setting attributes to the views the controller has access to. The controller must have references to its views. Those references are simple implicitly unwrapped optional (!) variables marked with @IBOutlet. So, @IBOutlet means that the view annotated with it is going to be linked to a view in the interface builder.
  • To reflect user actions in the model: This is done by having methods in the controller annotated with @IBAction, which will be linked to actions in views (such as a button tap). There are other ways other than using @IBAction, but that's good enough to start.

Let's say we have this view:

image

The functionality that we need to add to the controller is to respond to the tap/click event in the UIButton that says "Generate full name", so we can take the text property in the UITextField views for the first and last names, and replace the text in the UILabel that says "Full name".

In order to do this, we need references in the controller for:

  • firstNameTextField: UITextField!
  • lastNameTextField: UITextField!
  • resultLabel: UILabel!

Why are these Optional? Because when we instantiate the controller, the view isn't loaded yet! we know when the views are instantiated because the viewDidLoad method is executed. This is VERY important, it will save us from getting random crashes.

To generate an @IBOutlet

  • Open an editor in the right

Screen Shot 2021-04-25 at 15.46.04

  • In the right editor, open the class ViewController.swift

Screen Shot 2021-04-25 at 15.46.47

  • In the left editor, search for the view you want to link.
  • Keeping pressed the control key in the keyboard, drag and drop the view to any place of the controller code (not inside a method).

Screen Shot 2021-04-25 at 15.47.25

Screen Shot 2021-04-25 at 15.48.45

A simple way of ensuring this has worked correctly is to select the view controller in the left editor. In the last tab in the right panel we'll see the names of the @IBOutlet and @IBAction we've linked.

Screen Shot 2021-04-25 at 15.51.38

Apart from the @IBOutlet, we'll need to react to the action in the UIButton using an @IBAction, that, as we've already learned, it's a method that will be executed when some action occurs in the view.

@IBAction func generateNameButtonPressed() {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

The @IBAction for a button might be associated to different events of that button. In general, we'll use the event touchUpInside, which is the most standard tap on the button.

The steps to generate a @IBAction are exactly the same than for generating a @IBOutlet, except that at the end, we need to choose an action instead of an outlet in the last step.

image

image

Once views and events are connected, we can insert custom logic to the controller. In this case, we'll need to obtain the first name and last name from the UITextField views, and then assign the concatenation of them to the text property in the UILabel.

image

Practice

Create an app that is just a label with a 0 (zero) in the middle of the screen with two buttons, one at the left for decrementing the value of the counter label, and another at the right for incrementing the value.

Also... what if we add a textField to customize the amount we will increment or decrement when the buttons are pressed?

Top comments (0)