I want to perform a segue from a button within a custom UITableViewCell, but I don't know how to access the cell's contents when I push that button. I realize that this could be accomplished through didSelectRowAtIndexPath, however I have that method performing another function, and I would like to use the button I have created within the table cell.
Here is my perform segue method I'm having trouble with:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showComments"
{
let vc:CommentOnPostViewController = segue.destinationViewController as CommentOnPostViewController
var buttonPosition:CGPoint = sender?.convertPoint(CGPointZero, toView: self.feed) as CGPoint!
var path:NSIndexPath = self.feed.indexPathForRowAtPoint(buttonPosition) as NSIndexPath!
var postToCommentOn:PFObject = feedList[path.row] as PFObject
vc.post = postToCommentOn as PFObject
}
}
I tag the button in the cell when displaying it, and give it a target action:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
// There is code that goes here for creating and displaying the cell.
cell.commentButton.tag = indexPath.row
cell.commentButton.addTarget(self, action: "addComment", forControlEvents: UIControlEvents.TouchUpInside)
}
Here is the action that is called when pressing the button:
func addComment()
{
self.performSegueWithIdentifier("showComments", sender: self)
}
Any help is appreciated. Thanks!
So, select the first view controller, and then go to the top menu and click on Editor → Embed In → Navigation Controller. For this, we are going to select the “show” segue in the “Selection Segue” section. This means that when you tap on the cell, it will cause this segue to happen.
Create a Protocol with the Method, that will be called by the CustomCell's Delegate, defined on your TableViewController
//Pass any objects, params you need to use on the
//segue call to send to the next controller.
protocol MyCustomCellDelegator {
func callSegueFromCell(myData dataobject: AnyObject)
}
Now use the Protocol on your UITableViewController
class MyTableViewController : UITableViewController, MyCustomCellDelegator {
//The usual Defined methods by UIViewController and UITableViewController
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Set the CustomCell new Delegate
var cell = tableView.dequeueReusableCellWithIdentifier(customIdentifier) as MyCustomCell
cell.delagete = self
return cell
}
//MARK: - MyCustomCellDelegator Methods
func callSegueFromCell(myData dataobject: AnyObject) {
//try not to send self, just to avoid retain cycles(depends on how you handle the code on the next controller)
self.performSegueWithIdentifier("showComments", sender:dataobject )
}
}
Define the Delegate on your Custom Cell and the Call inside your New Button the Delegate Function.
class MyCustomCell : UITableViewCell {
var delegate:MyCustomCellDelegator!
@IBOutlet weak var myButton:UIButton
@IBAction func buttonPressed(sender:AnyObject){
var mydata = "Anydata you want to send to the next controller"
if(self.delegate != nil){ //Just to be safe.
self.delegate.callSegueFromCell(mydata)
}
}
}
Hopefully this can be clean and clear for you to understand and implement in your code.
I found an swiftier answer for passing data with a button in a dynamic cell to a new VC.
Setting up a Tableview, a custom cell (connect the cell with your created class and set a cell-identifier) and create a new VC and connect it via a segue (also set an identifier for the segue) to your current TableViewController
setting up your cell with the outlet (cellButton)
class CustomCell: UITableViewCell {
@IBOutlet weak var cellButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
CellForRowAt function in the TableViewController-Class
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomCell
//...Do stuff for your cell
cell.cellButton.tag = indexPath.row //or value whatever you want (must be Int)
cell.cellButton.addTarget(self, action: #selector(TableViewController.buttonTapped(_:)), for: UIControlEvents.touchUpInside)
}
set up the button method that's called by the target of the button
func buttonTapped(_ sender:UIButton!){
self.performSegue(withIdentifier: "customSegueIdentifier", sender: sender)
}
prepare for segue function
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "customSegueIdentifier") {
if let destination = segue.destination as? YourNewViewController {
if let button:UIButton = sender as! UIButton? {
print(button.tag) //optional
destination.valueViaSegue = button.tag
}
}
}
}
Hope this code will help you guys. keep coding ;)
Here's what I did
In your UITableViewCell class, added the following
protocol MyCustomCellDelegator {
func callSegueFromCell(myData dataobject: AnyObject)
}
class MyUITableViewCell: UITableViewCell {
var delegate:MyCustomCellDelegator!
.......
@IBAction func buttonPress (_ sender: Any){
if(self.delegate != nil){
self.delegate.callSegueFromCell(myData: )
}
}
}
And in the UITableViewController
class STVHomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, MyCustomCellDelegator {
.....
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "MyIdentifier") as? MyIdentifierCell {
// configure your cell
cell.configureCell(myIdentifier:)
// This line is important
cell.delegate = self
return cell
} else {
return MyIdentifierCell()
}
}
func callSegueFromCell(myData dataobject: AnyObject) {
print(dataobject)
self.performSegue(withIdentifier: "goToNextVC", sender: dataobject )
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With