James Frost
James Frost

Reputation: 33

Perform a segue using a button in a custom cell and passing on an object

I'm trying to write a tablet tracking app for my mother but I'm having an issue I'm using an edit button to access a static table view but it is refusing to pass on the medicine object.

I need to be able to get the indexPath in prepare(for:sender:) and I'd usually use tableView.indexPathForSelectedRow and then use the row to pull the right one from the array but as I'm using a button that's not possible.

I've tried using the tag to store the row, I've tried a protocol as suggested in other answers here but I've had no success. The app still crashes when I'm trying to go to the edit screen. I have my current code below, gone through too many iterations to list them all

@IBAction func editButtonTapped(_sender: UIButton) {
    let point = sender.convert(CGPoint.zero to self.tableView)
    buttonIndexPath = self.tableView.indexPathForRow(at: point)
    preformSegue(withIdentifier: "showDetails", sender: sender)
}

and my prepare(for:sender:) code is as follows

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetails" {
        let destination = segue.destination as! MedicineDetailTableViewController
        let selectedMedicine = medicines[(buttonIndexPath?.row)!]
        destination.medicine = selectedMedicine
    }
}

I apologise if this is something stupid that I'm missing but I'm at wit's end.

Upvotes: 2

Views: 216

Answers (2)

a.u.b
a.u.b

Reputation: 1609

In this case, I'm following these steps:

1) Add 'Your Edit Button' into your UITableViewCell and create IBOutlet.

class YourTableViewCell: UITableViewCell {
    @IBOutlet weak var yourEditButton: UIButton!
}

2) In your cellForRowAtIndexPath method, assign button tag as index.

 cell.yourEditButton.tag = indexPath.row

3) Create IBAction in your View Controller. Open storyboard and connect "your edit button" with this IBAction function.

class YourViewController: UIViewController {

    let selectedMedicine: Medicine? //your global Medicine variable

    @IBAction func editButtonTapped(_sender: UIButton) {
        //now you can access selected row via sender.tag

        selectedMedicine = medicines[sender.tag]
        preformSegue(withIdentifier: "showDetails", sender: nil)
    }
 }

Finally:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetails" {
        let destination = segue.destination as! MedicineDetailTableViewController
        destination.medicine = selectedMedicine
    }
}

Upvotes: 0

Prettygeek
Prettygeek

Reputation: 2531

You can setup delegate for for custom cell with function like

func buttonTapped(_ sender: UITableViewCell)

Then You can use sender to get IndexPath with indexPath(for:) on tableView and perform segue.

Then Your tableView(_:cellForRowAt:) can look like this:

tableView(_:cellForRowAt:){
   //setup other stuff and dequeue cell
   cell.delegate = self
   return cell

}

Upvotes: 1

Related Questions