iOS Storyboards: Segues and More

In this tutorial, you’ll learn how to connect view controllers to a storyboard, programmatically trigger segues, control visual components and respond to the user interactions. By Ehab Amer.

Leave a rating/review
Download materials
Save for later
Share
Update note: Ehab Yosry Amer updated this tutorial for iOS 13, Xcode 11 and Swift 5. Nicholas Sakaimbo wrote the original.

In the previous tutorial — iOS Storyboards: Getting Started — you learned how to build an app prototype using only storyboards. Your prototype had all the screens and included navigation and flow. In this tutorial, you’ll build full functionality and convert that prototype to a complete app.

Getting Started

Use the Download Materials button at the top or bottom of this tutorial to download the starter project. It has the storyboard you finalized in the previous part, and a few Swift files containing some of the app’s logic, but no code is connected to the storyboard yet. That’s what you’ll do now. :]

The Project navigator of your starter project looks like this:

Project Navigator

Along the way, you’ll create new view controllers and connect them to the existing storyboard. Time to get started.

Bringing the Players Screen to Life

Open Main.storyboard to take a look at all the scenes built in the previous part. The first screen you’ll give life to is the Players Scene, which has a table view. It was setup to use static cells and it already includes three cells.

To start, right-click on the View Controllers folder and select New File

New File Menu

Select Swift File and name it PlayersViewController.swift.

PlayersViewController

The only code included in the file is an import statement:

import Foundation

It imports the Foundation framework which includes basic classes like String and Date. Replace it with this instead.

import UIKit

This imports the whole UIKit framework instead, which depends on Foundation, so you can use classes declared in both.

To define your first scene, add the following to PlayersViewController.swift, after the import statement:

class PlayersViewController: UITableViewController {
  var playersDataSource = PlayersDataSource()
}

You have defined a new class named PlayersViewController, and it’s a subclass of UITableViewController. You also defined the property playersDataSource, which is an instance of PlayersDataSource. This property provides the list of players so you can focus on showing them in the table view and not worry about how they are saved and loaded.

This view controller is a subclass of UITableViewController, because the scene on the storyboard is a table view.

Storyboard PlayersViewController class

Note: UITableViewController is a subclass of UIViewController, but the main view in this scene is a UITableView. So, in this case, it’s more convenient to using a table view controller right away.

Now, use the new class in the storyboard.

Storyboard, Please Meet My New Class

Open Main.storyboard. Select the Player Scene that has a table view in the Document Outline and, in the Identity inspector, click the drop-down button beside the Class field. It will show all the classes in your project that can fit your selected object. In this case, select PlayersViewController.

Changing ViewController class

Now, when the storyboard creates an instance of this scene, it will be of class PlayersViewController. Next, you must configure the table view to display data dynamically.

Dynamic Cells

First, change the the type of the content in the table view from Static Cells to Dynamic Prototypes. Then, delete two of the cells in the table view, so that there’s just one left.

Next, select the remaining cell, open the Attributes inspector and enter PlayerCell in the Identifier field.

Change Cell Identifier

To tell the table view to create your custom cell, you need to be able to identify it. This is what the Identifier value is. It gives you the means to reference the cell you want from the code.

Next, add this extension at the end of PlayersViewController.swift:

extension PlayersViewController {
  override func tableView(
    _ tableView: UITableView,
    numberOfRowsInSection section: Int
  ) -> Int {
    playersDataSource.numberOfPlayers()
  }

  override func tableView(
    _ tableView: UITableView,
    cellForRowAt indexPath: IndexPath
  ) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(
      withIdentifier: "PlayerCell",
      for: indexPath)

    return cell
  }
}

You just created a new extension for PlayersViewController with two methods.
The first returns the number of cells to be displayed and the second creates and returns a cell using the identifier you set previously.

Note: Extensions are a great way to keep your code organized. You can define them in the same Swift file or in different files. Make it a habit to keep your code organized. You can learn more about extensions from Apple’s Swift docs.

Build and run, and you’ll see three identical cells. The information displayed on the cell is exactly what’s declared in the storyboard, multiplied by three. Time to make things more dynamic.

Simulator Screenshot

Defining a New Cell Class

The existing cell has two labels and one image, but there is no way to set these values dynamically via code. The default UITableViewCell doesn’t have access to such components.

Much like you did with the view controller, you’ll create a new cell class and define a reference between its components and the new class itself.

Right-click on the Views folder and select New File. This time, select Cocoa Touch Class. Then, set the name of the file to PlayerCell and make it a subclass of UITableViewCell.

New Cell File

This is a faster way to automatically create classes from Xcode instead of creating an empty file. It has everything already set up for you, and that boilerplate code will vary based on the subclass you specified.

For now, ignore the auto-generated methods and add this at the top of your class:

@IBOutlet weak var gameLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var ratingImageView: UIImageView!

Those are the references you’ll use to access the elements on the cell. But what’s that @IBOutlet? It’s a keyword for the storyboard and is short for Interface Builder Outlet. It tells the compiler that those properties will connect to some views on the storyboard.

Open Main.storyboard, select the cell in the Player Scene. In the Identity inspector, change the class to PlayerCell.

Change Cell class

Now, open the Connections inspector; you’ll see the following:

Connections Inspector

Those are the three properties that you defined in the class. Pretty smart, isn’t it? :]

Now, drag from the small circle beside the property name to the view on the cell that represents it.

Connecting Outlets

Do the same for all three to connect the views on the cell.

It’s now time to show real information about a player.