Search code examples
iosswiftuipopovercontrolleruitableviewrowaction

I want to open a new ViewController through UITableViewRowButtonAction


I have a UITableViewRowAction so when I slide there are 3 options from which I can choose. If I click on the Call button I want a new ViewController to pop over the whole screen. And if I click on a button inside the new ViewController 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
        self.tableView.dataSource?.tableView?(
            self.tableView,
            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)
        vc.view.addSubview(declineButton)
        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)

        return
    })

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.


Solution

  • 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: { 
    
                                                    })
        }
    
        rowActions.append(callAction)
    
        return rowActions
    }
    


    Just wire up your button with the IBAction

    class DetailViewController: UIViewController {
    
        var delegate: DetailDelegate?
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        @IBAction func didTapBtn(_ sender: AnyObject) {
            dismiss(animated: true, completion: nil)
        }
    }