jackios
jackios

Reputation: 165

How to dismiss previous Viewcontroller after presenting new Viewcontroller using Swift?

My Scenario, In my project I am maintaining three ViewController (Main, VC1 and VC2). In main ViewController I am maintaining UIButton, This button click to VC1 presenting model view controller. Again, VC1 I am maintain UIButton with action click to present model to VC2. After VC2 presenting I need to dismiss VC1.

//  presenting ViewController
var presentingViewController: UIViewController! = self.presentingViewController

self.dismissViewControllerAnimated(false) {
      // go back to MainMenuView as the eyes of the user
      presentingViewController.dismissViewControllerAnimated(false, completion: nil)
}

Upvotes: 3

Views: 5124

Answers (6)

Atul Gupta
Atul Gupta

Reputation: 51

You need to open vc2 from the mainVC - In order to do this you need a delegate method which will tell mainVC to close the current opened vc (i.e. vc1) and in the success block open vc2.

Code Snipet:-

dismiss(animated: false) { //Open vc2 present(vc2) }

Upvotes: 1

RajeshKumar R
RajeshKumar R

Reputation: 15778

Try this in VC2's close button action

var vc = self.navigationController?.presentingViewController
while vc?.presentingViewController != nil {
    vc = vc?.presentingViewController
}
vc?.dismiss(animated: true, completion: nil)

Upvotes: 2

PGDev
PGDev

Reputation: 24341

To solve the problem statement, what you can do is present VC2 using Main instead of VC1.

We can get the reference to Main in VC1 using

self.presentingViewController

When VC2 is presented, dismiss VC1 in the completionHandler of present(_:animated:completion:) method

class Main: UIViewController {
    @IBAction func onTapButton(_ sender: UIButton) {
        let vc1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "VC1")
        self.present(vc1, animated: true, completion: nil)
    }
}

class VC1: UIViewController {
    @IBAction func onTapButton(_ sender: UIButton) {
        let vc2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "VC2")
        vc2.view.backgroundColor = .blue
        self.dismiss(animated: false, completion: nil)
        self.presentingViewController?.present(vc2, animated: true, completion: nil)
    }
}

class VC2: UIViewController {

}

This approach is giving the expected output. Let me in case anything else is required.

Upvotes: 1

Rishab
Rishab

Reputation: 1957

There is a present(_:animated:completion:) method which takes a completion. Inside that you can dismiss your VC1.

Your code will look something like this

@IBAction func ButtonTapped(_ sender: Any) {
    present(VC2, animated: true) {
        dismiss(animated: true, completion: nil)
    }
}

Upvotes: 0

B K.
B K.

Reputation: 534

Hope this will work:

You need to have a UIViewController as a base, in this case MainViewController is the base ViewController. You need to use a protocol to call the navigation between Controllers.

you can do using protocol:-

In to your FirstViewController setting Protocol :

protocol FirstViewControllerProtocol {
    func dismissViewController()
}

class FirstViewController: UIViewController {

    var delegate:FirstViewControllerProtocol!

    override func viewDidLoad() {
        super.viewDidLoad()

        }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    @IBAction func goBack(sender: AnyObject) {
        self.dismissViewControllerAnimated(true) { 
            self.delegate!.dismissViewController()
        }
    }

Now in your MainViewController

class MainViewController: UIViewController, FirstViewControllerProtocol {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


@IBAction func goToFirstViewController(sender: AnyObject) {
    let viewController = self.storyboard?.instantiateViewControllerWithIdentifier(String(FirstViewController)) as! FirstViewController
    viewController.delegate = self
    self.presentViewController(viewController, animated: true, completion: nil)
}



//MARK: Protocol for dismiss
func dismissViewController() {
    if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier(String(SecondViewController)){
        self.presentViewController(viewController, animated: true, completion: nil)
    }
}

Upvotes: 1

Gaurav Tiwari
Gaurav Tiwari

Reputation: 44

In this case you need to call dismiss from the view controller over which your other view controllers are presented(Main in your case).

As you stated your situation in the question above Main presents VC1 and VC1 then presents VC2: then calling Main.dismiss(animated: true, completion: nil) will dismiss VC1 and VC2 simultaneously.

If you don't have a reference to the root controller(Main), you could chain a couple of presentingViewController properties to access it; Something like this in the topmost controller(VC2):

presentingViewController?.presentingViewController?.dismiss(animated: true)

I hope this helps.

Upvotes: 0

Related Questions