0

I am attempting to have the user segue to another view controller when tapping a cell. Currently I have my cell segue set up by doing the control drag in the story board to my view controller and then passing in the following code for a prepare(for segue...). Basically, there are my guard statements confirming I have the correct view controller and then I pass an object between them.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     super.prepare(for: segue, sender: sender)

     switch(segue.identifier ?? "") {

     case "ShowEventDetailsSegue":
        guard let navVC = segue.destination as? UINavigationController else {
            fatalError("Unexpected destination: \(segue.destination)")
        }

        guard let EventDetailViewController = navVC.viewControllers.first as? EventViewController else {
            fatalError("Unexpected navigation view controller: \(String(describing: navVC.viewControllers.first))")
        }

        guard let selectedEventCell = sender as? EventTableViewCell else {
            fatalError("Unexpected sender: \(String(describing: sender))")
        }

        guard let indexPath = tableView.indexPath(for: selectedEventCell) else {
            fatalError("The selected cell is not being displayed by the table")
        }

        let selectedEvent = events[indexPath.section]
        EventDetailViewController.event = selectedEvent


         default:
            fatalError("Unexpected Segue Identifier; \(String(describing: segue.identifier))")
     }
 }

I know that other people recommend calling something like

DispatchQueue.main.async { 
    self.present(myVC, animated: true, completion: nil)
}

(see here and also here)

but when I do that, I get an error "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller".

Basically, I want to be able to have the user only click one time on the cell and still be able to pass data over to the other view controller.

What is also strange is that this just started happening. I did not have this issue before today.

Surjeet Singh
  • 11,691
  • 2
  • 37
  • 54
thalacker
  • 2,389
  • 3
  • 23
  • 44
  • where have you added this code `self.present(myVC, animated: true, completion: nil)` ? – Amit Nov 20 '18 at 05:45
  • 2
    You need to EITHER trigger segue in code, OR set it in the storyboard. You are probably doing both, hence the exception. – Yevgeniy Leychenko Nov 20 '18 at 06:40
  • @Amit I added the code below my gaurd statements, right before the default. I am already triggering the segue by "tapping on the cell" for lack of a better term. @Evgeniy I agree. I am setting it currently in the story board, and then handling the logic in my `prepare( for segue...)` method. I would like to handle it this way, if possible. – thalacker Nov 20 '18 at 14:31
  • @Evgeniy I have tried it both ways, and I still have to tap twice for the cell to segue – thalacker Nov 21 '18 at 04:44

2 Answers2

0

So what you are doing is :

In tableView didSelectRowAt method you are adding :

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.performSegue(withIdentifier: "ShowEventDetailsSegue", sender: nil)
}

which triggers the delegate method:

override func prepare(for segue: UIStoryboardSegue, sender: Any?)

there is already a controller preparing to open and you are presenting a different controller programmatically, which obviously will throw an error.

Either you write a different logic for presenting view programmatically in tableView didSelectRowAt or you can shift the entire code in the second view controller viewDidLoad method.

Amit
  • 4,837
  • 5
  • 31
  • 46
  • Kinda. Basically, I believe I need to switch my code around, but I still want to `prepare` for the segue because I need to pass data over to the receiving controller. – thalacker Nov 21 '18 at 04:34
0

Turns out, the selection style of my cell is set to none.

cell.selectionStyle = UITableViewCellSelectionStyle.none

I don't want a selection style though, so the way around this is to make an asynchronous call

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    DispatchQueue.main.async {
        self.performSegue(withIdentifier: "ShowEventDetailsSegue", sender: nil)
    }
}

This now fixes the issue. For more info, check out this post.

thalacker
  • 2,389
  • 3
  • 23
  • 44