Search code examples
iosxcodeuitableviewswift3uistoryboardsegue

Swift Switching To and FromTable ViewController Issue Using Custom Segue


I have run into an issue when using a custom segue. I have two tableviews that I'm an trying to switch back and forth from. When I click on a cell in tableview1 it should take me to tableview2. I have a button on tableview2 that connects to the exit of the storyboard. From there it should take me back to tableview1 but whenever I press the button, the application crashes with a BAD_ACCESS error.

Here is my custom segue class:

class TableViewSegue: UIStoryboardSegue {

override func perform() {
    scale()
}

func scale () {
   let toViewcontroller = self.destination
    let fromViewcontroller = self.source
    let containerView = fromViewcontroller.view.superview
    let originalCenter = fromViewcontroller.view.center
    toViewcontroller.view.transform = CGAffineTransform(scaleX: 0.05, y: 0.05)
    toViewcontroller.view.center = originalCenter

    containerView?.addSubview(toViewcontroller.view)

    UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut, animations: {
    toViewcontroller.view.transform = CGAffineTransform.identity
    }, completion: { success in
    fromViewcontroller.present(toViewcontroller, animated: false, completion: nil) //The application crashes and highlights this line as the error.
    }) 
} 

}

I have implemented this method in my tableViewController1:

    @IBAction func prepareForUnwind(segue: UIStoryboardSegue) {

}

Not sure why the tableview2 does not dismiss.

EDIT: The issue had to do with needing a navigation controller.


Solution

  • The problem is that you are presenting the toViewcontroller each time a segue is performed. So the app presents table2 over table1, and then tries again to present table1 over table2 on the unwind.

    Modify your custom segue to check - essentially - which direction you're going:

    class TableViewSegue: UIStoryboardSegue {
    
        override func perform() {
            scale()
        }
    
        func scale () {
            let toViewcontroller = self.destination
            let fromViewcontroller = self.source
            let containerView = fromViewcontroller.view.superview
            let originalCenter = fromViewcontroller.view.center
            toViewcontroller.view.transform = CGAffineTransform(scaleX: 0.05, y: 0.05)
            toViewcontroller.view.center = originalCenter
    
            containerView?.addSubview(toViewcontroller.view)
    
            let fromP = fromViewcontroller.presentingViewController
    
            UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut, animations: {
                toViewcontroller.view.transform = CGAffineTransform.identity
            }, completion: { success in
    
                // if nil, we are presenting a new VC
                if fromP == nil {
                    fromViewcontroller.present(toViewcontroller, animated: false, completion: nil)
                } else {
                    fromViewcontroller.dismiss(animated: false, completion: nil)
                }
    
            })
        }
    
    }
    

    Note: This is assuming:

    1. you are not trying to push/pop within a UINavigationController ... you'd need to add some other checks to handle that.
    2. you are only going one-level-in, that is, you are not presenting, presenting, presenting, etc. and then trying to unwind.