1

I'm trying to move to a new storyboard when a button is tapped in a custom cell type, but having trouble with the custom class. I currently have this

class submitCell: UITableViewCell {
    @IBAction func cancelButton(_ sender: Any) {

    }

}

and I need the cancelButton to do this

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let viewController = storyboard.instantiateViewController(withIdentifier: "TripList") as! TripTableViewController
            self.present(viewController, animated: true , completion: nil) //Move

Except that .present isn't a method of UITableViewCell, only UIViewController. How can I get this functionality to happen?

Sam
  • 6,616
  • 8
  • 35
  • 64
  • 1
    You really shouldn't be doing this from a TableViewCell as it breaks MVC. You should really delegate the action to the tableViewController (or it's parent view controller). – Abizern Jul 21 '17 at 14:33

5 Answers5

3

Rather than trying to call the function in your custom cell, do that in your view controller. Here is what you need

class submitCell: UITableViewCell {

    var tapAction: ((UITableViewCell) -> Void)?

    @IBAction func cancelButton(_ sender: Any) {
        tapAction?(self)
    }
}

and then in your view controller

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    cell.tapAction = { [weak self] cell in self?.move()}
}

func move() {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier: "TripList") as! TripTableViewController
    self.present(viewController, animated: true , completion: nil) //Move
}

Note: You should capitalise the first letter of your class name. Check out Swift name conventions for more information.

Lawliet
  • 3,438
  • 2
  • 17
  • 28
1

First in the custom cell, bring the button into it and connect.

class submitCell: UITableViewCell {
    @IBOutlet weak var cancelButton: UIButton!
}

And now lets do what you want to do in the class where you use the button. In the class, where cell is created, do

cell.delegate = self
cell.cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)

then create one function that does:

private func cancelAction(sender: UIButton){
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier: "TripList") as! TripTableViewController
    self.present(viewController, animated: true , completion: nil) //Move
}
Bubu
  • 651
  • 8
  • 25
0

There are a fews ways to do that. - Create a delegate - Create a reference for your button, so you can use in your ViewController.

I'll link some cases, so you can choice the best approach for your case:

Reference Button

Delegate

0

You can delegate the function cancelButton to the viewController by having a reference to the button in your custom cell class.

Basically, first you need to make an outlet to the button in your custom cell :

@IBOutlet var button: UIButton!

And then in your viewController :

button.addTarget(self, action:#selector(cancelButton(_sender:)), for: .touchUpInside)

Declare the function :

    func cancelButton (_sender: UIButton) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier: "TripList") as! TripTableViewController
    self.present(viewController, animated: true , completion: nil) //Move
}

PS : If you have multiple buttons you can add them to the same action and control the behavior by a tag.

 button.tag = 0

 if ( _sender.tag == 0.) {
     // do tag 0
  } else ... 
Fares Benhamouda
  • 589
  • 8
  • 21
0

I would look at the delegate pattern.

Create a protocol for your UITableViewCell delegate

protocol SubmitCellDelegate: class {
    func cancelButtonPressed()
}

Add the delegate to your UITableViewCell subclass

class SubmitCell: UITableViewCell {
    weak var delegate: SubmitCellDelegate?

    @IBAction func cancelPressed(_ sender: UIButton) {
        delegate?.cancelButtonPressed()
    }
}

Implement the delegate in your UIViewController subclass

This must be implemented in the class that has the reference to your tableview cell.

class ViewController: UIViewController, SubmitCellDelegate {

    // ... 
    // wherever you create your cell
        submitCell.delegate = self
    // ...

    // Implement the SubmitCellDelegate function (Xcode will force you to)
    func cancelButtonPressed() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "TripList") as! TripTableViewController
        self.present(viewController, animated: true , completion: nil)
    }
}

Side note: it's good practice in most (all?) object-oriented programming language to use title case on class names (e.g. SubmitCell instead of submitCell).

Paolo
  • 3,825
  • 4
  • 25
  • 41