Search code examples
iosswiftmemory-leaksuiviewcontrollersegue

How to remove a UIViewController after having performed a segue?


As an exercise I would like to not use a navigation controller.

I have the following project:

storyboard screenshot with segues

The 2 push segues are triggered by each button in the center of the ViewControllers. They use the following custom class:

class CustomSegue: UIStoryboardSegue {
    
    override func perform() {
        
        weak var firstView = self.source.view as UIView?
        weak var secondView = self.destination.view as UIView?
        
        let screenSize = UIScreen.main.bounds.size
        
        secondView?.frame = CGRect(x: screenSize.width, y: 0.0, width: screenSize.width, height: screenSize.height)
        
        UIApplication.shared.keyWindow?.insertSubview(secondView!, aboveSubview: firstView!)
        
        UIView.animate(withDuration: 0.3, animations: { () -> Void in
            
            firstView!.frame = firstView!.frame.offsetBy(dx: -1 * screenSize.width, dy: 0.0)
            secondView!.frame = secondView!.frame.offsetBy(dx: -1 * screenSize.width, dy: 0.0)
            
        }) { (_) -> Void in
            self.source.present(self.destination, animated: false, completion: nil)
        }
        
    }
    
}

This goes extremely wrong because it creates a new ViewController object at each segue performed. The memory usage keeps going up and never down as UIApplication.shared.keyWindow.subviews is getting filled with UIViews...

The project I am working on has several ViewControllers which can call any other randomly. For this reason I didn't succeed to use UIViewController.dismiss(animated:completion:) because it systematically makes it go back to the previous ViewController.

How can I definitely remove the previous ViewController after having performed a segue?


Solution

  • Based on the comments, you don't want traditional "Navigation Controller" features - mainly, you don't need a "Back" button.

    So, one option would be to use Child View Controllers.

    Your "main" view controller would have nothing but a "container" view. On startup, you load your first VC as a Child VC, and add its view as a subview of the container. When you want to "navigate" to any other VC, load that VC as a Child VC, replace the current view in the container with the new ChildVC's view, and unload the current Child VC.