Passing Data with Segues

Learn how to pass data between ViewControllers in Swift using Storyboard Segues, from a master view to a detail view.

Passing Data with Segues

Note:

This tutorial demonstrates how to handle row selection in a UITableView and pass the corresponding data to another UIViewController to display detailed information.

Overview

When a user taps an item in a UITableView, you often want to display more details on a new screen. A common example is in social media apps where tapping a post opens a detailed view with the image and comments. This is achieved by using Segues and passing data between UIViewControllers.

In this tutorial, we will build a simple app that displays a list of superhero names in a UITableView. When a user taps a name, a new UIViewController will appear, showing the superhero's name and image.

Demo GIF

Reference:

Step 1: Setting up the Storyboard

Create TableView and Detail ViewController

  1. Open your Main.storyboard.
  2. Add a UITableViewController to your storyboard. This will be our main screen.
  3. Add a new UIViewController. This will be our detail screen.
  4. Create a new Swift file for your detail view controller, name it DetailsViewController.swift.
Create Swift File
  1. In the storyboard, select your new detail UIViewController. Go to the Identity Inspector and set its custom class to DetailsViewController.
Set Custom Class

Create a Segue

  1. Control-drag from a cell in your UITableViewController to the DetailsViewController.
  2. Choose Show from the popup menu to create a segue.
  3. Select the segue and go to the Attributes Inspector. Give it an identifier, for example, toDetailsVC.

Embed in Navigation Controller

To get a navigation bar with a back button, select your main UITableViewController and go to Editor > Embed In > Navigation Controller.

Embed in Navigation Controller

Step 2: Designing the Detail View

In your DetailsViewController on the storyboard, add a UIImageView and a UILabel. Connect them as outlets to your DetailsViewController.swift file.

// In DetailsViewController.swift
import UIKit

class DetailsViewController: UIViewController {
    @IBOutlet weak var heroImageView: UIImageView!
    @IBOutlet weak var heroNameLabel: UILabel!
    
    var selectedHeroName: String?
    var selectedHeroImageName: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        heroNameLabel.text = selectedHeroName
        if let imageName = selectedHeroImageName {
            heroImageView.image = UIImage(named: imageName)
        }
    }
}

Step 3: Populating the TableView

In your main ViewController.swift, set up the data and UITableViewDataSource methods.

Prepare the Data

First, add your images to the Assets.xcassets folder. Then, create arrays to hold your data.

// In ViewController.swift
var heroNames = [String]()
var heroImageNames = [String]()
var selectedName = ""
var selectedImage = ""

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Populate data
    heroNames.append("Batman")
    heroNames.append("Superman")
    heroNames.append("Iron Man")
    
    heroImageNames.append("batman")
    heroImageNames.append("superman")
    heroImageNames.append("ironman")
}
Populate data arrays

TableView DataSource Methods

Implement the necessary UITableView methods.

// In ViewController.swift
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return heroNames.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell()
    cell.textLabel?.text = heroNames[indexPath.row]
    return cell
}
TableView DataSource methods

Step 4: Passing Data with a Segue

Handle Row Selection

Use didSelectRowAt to detect a tap and trigger the segue.

// In ViewController.swift
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    selectedName = heroNames[indexPath.row]
    selectedImage = heroImageNames[indexPath.row]
    performSegue(withIdentifier: "toDetailsVC", sender: nil)
}
didSelectRowAt implementation

Prepare for Segue

Implement the prepare(for:sender:) method to pass the selected data to the DetailsViewController before the transition happens.

// In ViewController.swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "toDetailsVC" {
        if let destinationVC = segue.destination as? DetailsViewController {
            destinationVC.selectedHeroName = selectedName
            destinationVC.selectedHeroImageName = selectedImage
        }
    }
}
prepare for segue implementation

Now, when you run the app, tapping a hero's name in the list will take you to the detail screen, which will display the correct name and image.


Note:

Using prepare(for:sender:) is the standard way to pass data between ViewControllers when using Storyboard segues. This keeps your code clean and organized.