UITableView vs UICollectionView Segue

1 minute read

This article describes the difference between a UITableView segue from a UICollectionView segue. If you first learned the UITableView segue you will be surpised because using the same method on a UICollectionView produces a different result. It took me some Googling to find the solution.

The first section describes the UITableView segue followed by the UICollectionView segue.

UITableView Segue

UITableView Segue

In the UITableView example we have a UITableViewController named MyViewController with a segue to another UITableViewController named MyDetailViewController. The segue identifier (1) is ShowHistoryDetail.

Before a segue is performed, you can set a property in the destination view controller via the instance method prepare(for:sender:).

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if segue.identifier == "ShowHistoryDetail" {
    let controller = segue.destination as! MyDetailViewController
    controller.item = sender as? Item
  }
}

When a UITableView row is tapped, the UITableViewDelegate is informed via the tableView(didSelectRowAt:) instance method. The item corresponding to the row is then sent to the destination view controller with the performSegue(withidentifier:sender:) method.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  var item = items[indexPath.row]
  performSegue(withIdentifier: "ShowHistoryDetail", sender: item)
}


UICollectionView Segue

UICollectionView Segue

In the UICollectionView example we have a UICollectionViewController named MyViewController which will segue to a UITableViewController named MomentDetailViewController. UICollectionView contains a UICollectionViewCell (1). The segue identifier (2) is MomentDetail.

This is where the UICollectionView differs from the UITableView. In a UICollectionView, connecting a segue from the storyboard is enough to perform the segue. If you call performSegue when the cell is selected, the segue is performed twice!

To set the destination view controller property to the corresponding selected cell, do it from the prepare(for:sender:) like so:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if segue.identifier == "MomentDetail" {
    if let cell = sender as? UICollectionViewCell, let indexPath = self.collectionView.indexPath(for: cell){
      let controller = segue.destination as! MomentDetailViewController
      controller.item = items[indexPath.item]
    }
  }
}