Most iOS applications that display multiple content also contain multiple view controllers. If your application is not based on navigation controllers or TAB bar controllers, but rather on a single view, loading and presenting the various view controllers to the user is a task that must be done manually. Loading a view controller through a storyboard or purely programmatically is generally not a daunting task, but how easy or straightforward is it all for a new developer?

This is a two-part tutorial, in which I’ll show you the various techniques you can use to load and render view controllers by covering all possible scenarios:

Create and execute segues directly from Interface Builder; This is a purely graphical approach. Create a segue in Interface Builder, but execute it in code; A hybrid approach. Load the graphics designed in the Interface Builder view controller programmatically from the storyboard and render it. Loading and rendering view controllers without storyboarding at all; 100% programmatic method.

In addition to the above, I’ll show you how to send data back and forth between view controllers after the demo is complete. However, this will not happen in this article, as it is the subject of Part 2.

Although this article is intended for beginners, familiarity with Xcode and some basic iOS concepts is essential. If you find something outside of the subject that you don’t understand or want more details, a quick search on StackOverflow, or often on the web, can be helpful.

What can you read in this article……

    1. An introduction to
    1. Technique #1: A completely graphical approach — using segues
    1. Technique #2: Hybrid approach — Implementing Segues in code
    1. Technique #3: For happy designers and programmers — load and render view controllers from storyboard files in code
    1. Tip #4: For code aficionados — a completely procedural approach
    1. conclusion

An introduction to

To try out the concepts we’ll see in the next section, you must create a simple Xcode project. So, launch Xcode, start creating a new project and select Single View App as your application template.

Go ahead, name the project (I’ll call it VCTechniques), find a place on your computer to save it, and complete its creation.

When you’re ready, you must add three new view controllers, which we’ll use to demonstrate the various topics we’ll discuss in this article. The process for adding a new view controller is simple: first press Ctrl + N on your keyboard, then select Cocoa Touch Class as the template for the new file.

In the next step, make sure UIViewController is the value of the Subclass of: field, and then type the name of our new class: FirstViewController.

Proceed to the next step and complete the creation of the new view controller. Then, repeat the process twice more and add the following view controller:

  • Second view controller
  • Third view controller

Once done, feel free to delete the default viewController.swift file automatically created by Xcode. At the end of all the above steps, you should be able to see the following list of files (among others) :

One last thing must be done. Open the main.storyboard file and select the ViewController object in the ViewController scene (yellow icon). Then open the identity checker and set FirstViewController to the class of the view controller:

Technique #1: A completely graphical approach — using segues

According to Apple documentation:

A SEGUE defines the transition between two view controllers in your application’s storyboard file. The starting point for a transition is a button, table row, or gesture recognizer that initiates the transition. The endpoint of the Segue is the view controller that you want to display.

In fact, segues in Interface Builder represent a connection between two view controllers. It performs at user time:

  • Either interact with the control in the first view controller (for example, a button) that triggers the segue, or
  • Perform another operation that triggers the segue programmatically, such as a gesture recognizer (more on this approach in the next section).

The way a segue presents a view controller that it’s connected to can be animated or non-animated. If it is animated, a small number of predefined transitions are available. If that’s not enough, you can also make and use custom transitions. It is important that a segue have a unique identifier so that it can be distinguished from all segues that exist in the project.

To see how segues are created, in the main.storyboard file, drag a new view controller Object from the Object Library in the Xcode Utilities pane onto the canvas as follows:

Once added, change the background color to be different from the first view controller (I set r: 149, G: 165, B: 166), and add a button that lets us turn off the view controller after rendering. Then, click the View Controller object (the yellow icon at the top of the scene) and go to the identity checker. From there, change the class to SecondViewController. As you know, our goal is to segue from FirstViewController and render SecondViewController.

Next, add a button to the first view controller. We will create a new transition that we will trigger from this button.

Now it’s time to create a transition. Click the button you just created while holding down the Ctrl key on your keyboard. Start dragging the mouse over the SecondViewController scene until it is on top of it and the entire scene is selected, as follows:

When you release the mouse and Ctrl key, a small pop-up window appears with the following options:

Click the Present Modally option to create the segue. You’ll verify this by seeing a blue line with arrows connecting the two view controller scenes. Click on the segue itself, then open the Utilities pane and go directly to the Attributes Inspector. In the Identifier field, set a unique value for the segue (for example, idSegueSecondVC). From the rest of the options displayed there, you will most likely want to change a few of them, such as the default transition, or whether to animate the new view controller.

Time to test it out! Run the project using the emulator and notice that the SecondViewController is displayed when the big red button is clicked.

To close the new view controller and return to the first controller, you must do the following:

Open SecondViewController. Swift file, and add the following method stubs:

@IBAction func dismissMe() {
    self.dismiss(animated: true, completion: nil)
}
Copy the code

Save the file and return to the main.storyboard file, select the SecondViewController scenario, and then open the Connections inspector in the Utilities pane. In the Received Actions section, you will see the method you just created. Click the circle on the right, and then drag toward the Dismiss Me button; A blue line will be created to show the connection:

Select the Touch Up Inside event from the pop-up window and test again:

Technique #2: Hybrid approach — Perform segues in code

All of the above steps involve a purely graphical way to start the segue and render another view controller. However, this is not always possible, and many times you also need to trigger segues programmatically. To do this, you must “break” your work in Interface Builder and code.

The general idea is to create segues between interested view controllers in The Interface Builder, rather than starting from the control that can actually trigger it, like the button we used in the previous section. Instead, segues are performed programmatically in code.

For our example, let’s create a new transition between the first and second view controllers. This time, however, we’ll start the segue from the view controller object instead of the big red button as we did last time in the FirstViewController scenario:

Select the Present Modally option again in the pop-up window, then click the new segue and open the Attributes inspector. Type another identifier for this identifier (for example, idSegueSecondVC_2) and specify a different transformation from the default identifier as needed. Save the Main. The storyboard file, then open the FirstViewController. Swift.

Here, we’re going to create a click-gesture recognizer and add it to the view of FirstViewController, and we’re going to set it up so that every time we double click on it, SecondViewController is displayed. Go to the viewDidLoad() method and add the following:

override func viewDidLoad() {
    super.viewDidLoad()
        
    let doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleDoubleTap))
    doubleTapGestureRecognizer.numberOfTapsRequired = 2
    self.view.addGestureRecognizer(doubleTapGestureRecognizer)
}
Copy the code

With the above lines, we create a new click-gesture recognizer, and we specify two clicks to trigger it and add it to the view controller’s view. HandleDoubleTap () is a method that calls our view every time we double-click. It doesn’t exist yet, so let’s define it now. In its body, the only thing we want to do is trigger our new segue, which, as you’ll see, is just a one-line operation:

@objc func handleDoubleTap() {
    self.performSegue(withIdentifier: "idSegueSecondVC_2", sender: self)
}
Copy the code

Notice how important the segue identifier is, because that identifier specifies the segue we want to perform.

Now by testing the application, the SecondViewController is shown to us every time we double-click anywhere in the view.

Technique #3: For happy designers and programmers — load and render view controllers from storyboard files in code

If you like coding, but leave the Interface Builder to design the UI of your view controller without creating segues graphically, then this section is definitely for you. Our goal here is to see how we load and render a view controller that exists in the storyboard, but this time we’re not going to create a segue at all.

For demonstration purposes, we’ll stick with SecondViewController. However, before we continue, let’s add a new button in the FirstViewController scenario. So open the main.storyboard file and drag a new button below the first one, as shown below, and specify the title Load from storyboard:

Next, select the SecondViewController scene object (yellow icon) and open the identity checker. We must set up a storyboard ID so that we can reference it later in our code. In the identity checker, set the value idSecondVC to the Storyboard ID field:

Save your storyboard file, then switch to the FirstViewController file. To that, add the following actions, which we will later connect to a new button called Load from Storyboard:

@IBAction func presentSecondVC() {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if let secondVC = storyboard.instantiateViewController(withIdentifier: "idSecondVC") as? SecondViewController {
        self.present(secondVC, animated: true, completion: nil)
    }
}
Copy the code

The code above loads the SecondViewController view controller from the main storyboard and renders it. With more details, these lines do the following:

In the first line of code, we access the storyboard named Main, which is the default storyboard that exists in the project. Obviously, if you have more storyboards and you want to access different storyboards, you can provide the correct name as the first parameter in the initializer above. Next, we try to instantiate the view controller using the identifier idSecondVC, which we specified earlier in the Identity inspector in Interface Builder. This identifier is how we refer to the correct view controller in our storyboard file. Note that we cast to SecondViewController to specify the exact class of the view controller we loaded, and if this process is successful, the view controller instance will remain in the object. After secondVC loads successfully, we modally render the second view controller. If you want to change the default transition between two view controllers and select another one of the predefined transitions (as you did in Interface Builder with segue), then modify this method by adding the lines that are displayed before displaying the new view controller:

@IBAction func presentSecondVC() {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if let secondVC = storyboard.instantiateViewController(withIdentifier: "idSecondVC") as? SecondViewController {
        // Add this line to select another transition.
        secondVC.modalTransitionStyle = .crossDissolve
        
        self.present(secondVC, animated: true, completion: nil)
    }
}
Copy the code

In addition, notice that we keep the instance of SecondViewController as a local property. Sometimes, however, you might want to have a class attribute that holds the instance so that you can refer to it outside of the method that loaded it. In this case, let’s declare the following properties at the beginning of the FirstViewController class:

class FirstViewController: UIViewController { var secondVC: SecondViewController! . }Copy the code

Finally, let’s update our method as follows:

@IBAction func presentSecondVC() {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if let secondVC = storyboard.instantiateViewController(withIdentifier: "idSecondVC") as? SecondViewController {
        secondVC.modalTransitionStyle = .crossDissolve
        self.present(secondVC, animated: true, completion: nil)
        
        // Keep the SecondViewController instance to a class property.
        self.secondVC = secondVC
    }
}
Copy the code

Before we can test the application, we need to connect the presentSecondVC() action method to the new button. So, open the main. storyboard file and select the FirstViewController scenario. In the Connections inspector, find the above Actions under the Received Actions section. Click the circle on the right and start dragging towards the new red button; Release the mouse when you are over it and then select the Touch Up Inside event from the pop-up window to establish the connection.

Now by testing the application, you will see that the SecondViewController is displayed when we click the second button we added in this step. The few lines above do all the “magic” required.

Technique #4: For code Junkies – A completely procedural approach

If you like creating user interfaces in code, or if you’ve just decided that you don’t like Interface Builder and storyboards anymore, this solution is for you. In this scenario, we’re going to use ThirdViewController as the view controller we’re going to show, but we’re not going to do any design in Interface Builder; In fact, we won’t even add scenes to the storyboard. Everything will happen in the code.

Let’s begin, let’s open the ThirdViewController. Swift file. We’re not going to do too much UI here; We’re going to keep it simple, we’re just going to change the background color of the view, and we’re going to add a button that lets us turn off the view controller. So add the following code at the beginning of the ThirdViewController class to create a property for the close button and perform some basic configuration:

class ThirdViewController: UIViewController { lazy var dismissButton: UIButton = { // Initialize a custom button. let button = UIButton(type: .custom) // Set the title and title color. button.setTitle("Dismiss Me", for: .normal) button.setTitleColor(.white, for: .normal) // Set the background color. button.backgroundColor = UIColor(red: 1.0, Green: 0.17, Blue: 0.33, alpha: Specify the method that should be called when the button is tapped. Button. AddTarget (self, action: #selector(self.dismissMe), for: .touchUpInside) // Prevent the view from creating constraints automatically for this button. button.translatesAutoresizingMaskIntoConstraints = false return button }() ... }Copy the code

The comments above make it easier to understand the code. As you can see, we didn’t do anything special with the button above, we just set its title, title color, and background color. The way that we dismissMe as an action target when the button is clicked is as follows:

@objc func dismissMe() {
    self.dismiss(animated: true, completion: nil)
}
Copy the code

Even if we set some properties for the button, we still need to add it to the root view of the view controller and specify its size and location. Let’s create a new way to do this:

func configureDismissButton() { // Add the button to view. self.view.addSubview(self.dismissButton) // Align the button horizontally to the view. NSLayoutConstraint(item: self.dismissButton, attribute: .centerX, relatedBy: .equal, toItem: Self. view, attribute:. CenterX, Multiplier: 1.0, constant: 0.0). IsActive = true // Place it close to the bottom of the view. NSLayoutConstraint(item: self.dismissButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -dismissbutton). IsActive = true // Set width and height. NSLayoutConstraint(item: self. DismissButton, attribute: dismissButton; .width, relatedBy:.equal, toItem: nil, attribute:.notanattribute, Multiplier: 1.0, constant: 119.0). IsActive = true NSLayoutConstraint(item: self. DismissButton, attribute:.height, relatedBy:.equal, toItem: dismissButton; Nil, attribute:.notanattribute, Multiplier: 1.0, constant: 36.0).isactive = true}Copy the code

Both size and position are specified using constraints.

This method must be called, preferably before the view appears. So, implement the viewWillAppear(_:) method and add the next thing to it:

override func viewWillAppear(_ animated: Bool) {super. ViewWillAppear (animated) self. The backgroundColor = UIColor (green, red, 0.0:0.69, blue: 0.92, alpha: 1.0) the self. ConfigureDismissButton ()}Copy the code

Two different tasks happen here: we call the configureDismissButton() method that places the close button into the view, and we also change the background color of the view.

The UI for ThirdViewController is now ready. It’s time to get to the real focus of this section, and see how we load and render this view controller designed entirely in code. Save this file, go to the FirstViewController. Swift, we will create a new action (IBAction) method. All we had to do was write two lines of code, and we were done.

@IBAction func presentThirdVC() {
    let thirdVC = ThirdViewController()
    self.present(thirdVC, animated: true, completion: nil)
}
Copy the code

Well, it’s that simple! We just initialize the view controller as we normally do for objects and classes and render it.

Before we can test the above, we need to trigger the action in some way, so let’s add another button to the FirstViewController scene. Open the main.storyboard file and add a new button called Third View Controller. Once you place it on the view, follow the same steps as in the previous section and connect the IBAction method above to the button’s Touch Up Inside event (open the connection inspector in the utilities pane, find the method and start dragging the button from the circle to the right).

Now we can test it! If you want to use a transformation other than the default transformation, you learned how to do this from the previous section. You just need to add the following lines and specify your preferred transitions:

@IBAction func presentThirdVC() {
    let thirdVC = ThirdViewController()
 
    thirdVC.modalTransitionStyle = .partialCurl
 
    self.present(thirdVC, animated: true, completion: nil)
}
Copy the code

Finally, all of the above operations:

conclusion

In this article, I’ve shown you four different ways to load and render a view controller. There is no better or worse approach, all approaches are equally good, and which one you will use depends on how you prefer to develop your application. If you are a programmer who uses Interface Builder and Storyboards extensively, the first two methods are for you. Conversely, if you create everything in your code, the last approach is probably what you need most. Personally, I usually fall somewhere between technologies #3 and #4, but I use the other two as well if necessary.

Now that we know how to load and render view controllers in various ways, the next step is to see how we pass values between them. This is the subject of the next part of this two-part tutorial, don’t miss it because there are interesting things to read; We won’t stop at the usual methods, there’s more to talk about.

Hope you like this… Have fun!

This is a link to download what you read in this article as a single project.

Recommended at the end of the article: iOS popular anthology

IOS Interview Basics (part 1)

IOS Interview Basics (part 2)

IOS Interview Basics (part 3)

IOS Interview Basics (4)

IOS Interview Basics (5)