0

I have a tableview inside a view controller, that is connected to 3 different view controller by a segue. Each one has an identifier.

In order to perform a segue to the corresponding view controller, I have created an array that contains the identifiers for each segue. like so :

var tableauSegues = ["versChapitre1", "versChapitre2", "versChapitre3"]

In order to manage the segue according to the index of the array, I chose to use a for in loop inside of an iB action, like this:

@IBAction func versHistoire(_ sender: UIButton) {

    for i in tableauSegues {

        performSegue(withIdentifier: i, sender: self)
    }

}

the problem is that all 3 segues are performed. I only want to perform one segue at the time.

any idea ?

LEKYSMA
  • 141
  • 10
  • What decides which segue is performed? The table cell's index? – Magnas Mar 23 '19 at 15:06
  • Why are you looping ? Is that single button is used to segue on 3 different controller? – Tushar Sharma Mar 23 '19 at 15:11
  • Isn't the answer pretty obvious, don't perform a `for` loop. Explain what it is you want to do in that Action func, performe one segue I suppose but which one? – Joakim Danielson Mar 23 '19 at 15:12
  • @TusharSharma i have a single prototype cell that returns 3 different tableview cell when the app loads. since they are dynamic cells, I cannot link each cell to a view controller via segue. I am trying to bypass that linking the VC that holds the table view cell with the different view controller (one for each cell) through a segue, and by creating an array that contains all the identifiers for each segue. – LEKYSMA Mar 23 '19 at 15:14
  • You shouldn't use for each loop in this case. If this UIButton the same for all cells you can: 1) Get UIButton in cellForIndexAtIndexPath method and set tag for button, then on button action switch "sender.tag" and use needed identifier to perform segue. 2) Do something like this [link](https://stackoverflow.com/questions/28894765/uibutton-action-in-table-view-cell) 3) Or like [this](https://fluffy.es/handling-button-tap-inside-uitableviewcell-without-using-tag/) – Ildar.Z Mar 23 '19 at 15:17
  • @LEKYSMA From what I understood from your question, what you want to do is : You have a single tableView cell (say custom made) and that cell has a button in it . You are reusing that cell to create 3 cells inside your tableView and you want to open different ViewController for each button tapped inside a cell . Am I correct? – Shubham Bakshi Mar 23 '19 at 15:31

1 Answers1

1

Obviously, you want to avoid looping, but instead want to just use tableauSegues[row]. But the trick is how to get the row.

Bottom line, you should let the cell handle the tapping of the cell, and have the cell tell the table view controller when its button was tapped. But the trick is that when it does that, it should supply a reference to itself when it does that, so that the view controller can determine which row had its button tapped.

Thus, remove your existing @IBAction directly between the button and the view controller, and instead, hook it up to an @IBAction in the cell’s base class.

//  CustomCell.swift

import UIKit

protocol CustomCellDelegate: class {
    func didTapButton(_ sender: Any, in cell: CustomCell)
}

class CustomCell: UITableViewCell {
    @IBOutlet weak var customLabel: UILabel!

    static let preferredReuseIdentifier = "CustomCell"

    weak var delegate: CustomCellDelegate?

    func configure(text: String, delegate: CustomCellDelegate) {
        customLabel.text = text
        self.delegate = delegate
    }

    @IBAction func didTapButton(_ sender: Any) {
        delegate?.didTapButton(sender, in: self)
    }
}

Note, when I configure that cell, I’m going to have the table view provide not only whatever values need to be displayed in the cell, but also indicate that it is the delegate for that cell:

//  ViewController.swift

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!

    var tableauSegues = ["versChapitre1", "versChapitre2", "versChapitre3"]
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableauSegues.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: CustomCell.preferredReuseIdentifier, for: indexPath) as! CustomCell
        cell.configure(text: "...", delegate: self)
        return cell
    }
}

extension ViewController: CustomCellDelegate {
    func didTapButton(_ sender: Any, in cell: CustomCell) {
        let row = tableView.indexPath(for: cell)!.row
        let identifier = tableauSegues[row]
        performSegue(withIdentifier: identifier, sender: self)
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044