devtimg devtimg - 9 months ago 68
Swift Question

I want to open a new ViewController through UITableViewRowButtonAction

I have a

so when I slide there are 3 options from which I can choose. If I click on the
button I want a new
to pop over the whole screen. And if I click on a button inside the new
I want it to be dismissed.

On click on the Call button opens a ViewController as popover
My UITableViewRowAction

This opens after my click on the button and this should dismiss on click on the bottom x-button
My ViewController as popover

This is my code

func buttonToDismiss (sender: AnyObject) {

self.presentedViewController?.dismiss(animated: true, completion: nil)

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

let callButton = UITableViewRowAction(style: .default, title: "Call", handler: { (action, indexPath) in
commit: .delete,
forRowAt: indexPath)

let vc = UIViewController(nibName: nil, bundle: nil)
vc.view.frame = CGRect(x: 0, y: 0, width: 100, height: 200)
vc.view.backgroundColor = UIColor(red: 62/255.0, green: 70/255.0, blue: 80/255.0, alpha: 1.0)
vc.modalPresentationStyle = .popover

let declineButton = UIButton()
declineButton.frame = CGRect(x: 150, y: 484, width: 75, height: 75)
declineButton.backgroundColor = UIColor(red: 36/255.0, green: 44/255.0, blue: 55/255.0, alpha: 1.0)
declineButton.tintColor = UIColor.white
declineButton.layer.cornerRadius = declineButton.frame.size.height / 2
declineButton.layer.masksToBounds = true
declineButton.clipsToBounds = true
declineButton.setTitle("X", for: .normal)
declineButton.addTarget(self, action: Selector(("buttonToDismiss:")), for: UIControlEvents.touchUpInside)
let popover = vc.popoverPresentationController!
let cell = tableView.cellForRow(at: indexPath)!

var cellAbsolutePosition = cell.superview!.convert(cell.frame.origin, to: nil)
cellAbsolutePosition.x = cell.frame.width - 60
popover.sourceRect = CGRect(origin: cellAbsolutePosition, size: cell.frame.size)
popover.sourceView = tableView

self.present(vc, animated: true, completion: nil)


I know that the code is I think very chaotic but I'm not yet very good at programming apps.

I appreciate any help and thank you in advance for your efforts.

Answer Source

Do this instead of what you are doing:

  1. Create the ViewController that you want to present when call action is selected
  2. Place the dismiss button on that ViewController and wire it to an IBAction
  3. When user selects call action, instantiate that ViewController from the storyboard and simply present it

Here's a simple example:

Say this is the ViewController that you want to present when call action is triggered View Controller to be presented

Instantiate and present the ViewController in the call action

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    var rowActions = [UITableViewRowAction]()

    let callAction = UITableViewRowAction.init(style: .default,
                                               title: "Call") { (action, cellPath) in
                                                //instantiate the view controller with storyboard ID
                                                let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
                                                self.present(vc, animated: true, completion: { 



    return rowActions

Just wire up your button with the IBAction

class DetailViewController: UIViewController {

    var delegate: DetailDelegate?

    override func viewDidLoad() {

    override func didReceiveMemoryWarning() {

    @IBAction func didTapBtn(_ sender: AnyObject) {
        dismiss(animated: true, completion: nil)