简体   繁体   中英

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)
}

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)

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.

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 (ie vc1) and in the success block open vc2.

Code Snipet:-

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

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)
    }
}

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.

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)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM