A duplicated segue processing with UIStoryBoardSegue between two UIViewControllers

358 Views Asked by At

I have two screens. The first is based on UITableView instance. When I tap cell, function tableView(_:didSelectRowAt:) triggers:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    selectedEmg = selectedEmergencies[indexPath.row]
    performSegue(withIdentifier: "ShowMoreInfoAboutEmg", sender: self)
}

Here is storyboard:

storyboard

But in fact, the segue "ShowMoreInfoAboutEmg" duplicates itself and second screen.

enter image description here

I can cut performSegue(withIdentifier:sender:) and the transition between screens will work correctly. However I need to transfer data from UITableViewCell instance to remote UIViewController's property. Otherwise I get something like this:

enter image description here

prepare(for:sender:) starts to work earlier than tableView(_:didSelectRowAt:) and remote view controller gets nil object from cell. Any tips, guys?

The decision is found.

The simple and useful UITableView's property indexPathForSelectedRow.

I didn't touch my storyboard but I removed tableView(_:didSelectRowAt:) implementation completely and just have added one line. It's enough to use prepare(for:sender:) totally. The general implementation is something like below:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "SomeCustomIdentifier" {
            guard let remoteViewController = segue.destination as? CustomViewController else {
                fatalError("CustomViewController instance is not found ")
            }
            selectedItem = items[(self.customTableView.indexPathForSelectedRow?.row)!]
            remoteViewController.selectedItemFromTable = selectedItem
        }
}
2

There are 2 best solutions below

1
Alex Zarr On

Maybe it will be much simpler:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let selectedEmg = selectedEmergencies[indexPath.row]
    if let vc = storyboard?.instantiateViewController(withIdentifier: "EmgDetailsPresenter") as? EmgDetailsPresenter {
        vc.selectedEmgFromTable = selectedEmg
        navigationController?.pushViewController(vc, animated: true)
    }
}

P.S. Don't forget to remove segue in Storyboard and add Storyboard ID to EmgDetailsPresenter

1
Jarad Kears On

So basically you're calling didselectrow from the code and also the segue from the cell in the story board. Delete the segue linking the cell in the Showmoreinfoaboutemg. Then create a segue from the whole showmoreinforaboutemg viewcontroller to the the one it is supposed to go to. Give it the same reuse identifier and problem solved

Edit: the issue is that you are calling the segue twice once on click in the story board and the select time on click in the code with did select row.