Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace ViewController in Swift?

Tags:

ios

swift

I have presented ViewController1 using this code:

let vc1 = ViewController1()
present(vc1, animated: true, completion: nil)

Now, I want to show ViewController2 in ViewController1.

@IBAction func buttonEvent(_ sender: UIButton) {
    let vc2 = ViewController2()
    self.present(vc2, animated: true, completion: nil)
}

The problem is: I want to show the ViewContoller2 while the current ViewController is being dismissed when the button event is called.

And I want to animation while doing this.

Thank you.

like image 926
etnclp Avatar asked Dec 01 '17 08:12

etnclp


2 Answers

You may achieve this through navigationController as follows:

guard var viewControllers = sourceViewController.navigationController?.viewControllers else { return }

// Popped ViewController not used
_ = viewControllers.popLast()

// Push targetViewController
viewControllers.append(targetViewController)

sourceViewController.navigationController?.setViewControllers(viewControllers, animated: true)

Get viewControllers in your navigation stack at first. Pop the current and append the target one. Then, set your stack to updated viewControllers.

Additions

(For those who do not use navigationController)

I realized a possible problem in the given answer. Thus I want to make this addition. Check documentation of parent before continue. I want to lay emphasis on this part:

If the recipient is a child of a container view controller, this property holds the view controller it is contained in. If the recipient has no parent, the value in this property is nil. Prior to iOS 5.0, if a view did not have a parent view controller and was being presented, the presenting view controller would be returned. On iOS 5, this behavior no longer occurs. Instead, use the presentingViewController property to access the presenting view controller.

In brief, if you want to dismiss the current UIViewController (sourceViewController) and present the next one (targetViewController), you should make the present() call from presentingViewController of the current.

weak var presentingViewController = self.presentingViewController

sourceViewController.dismiss(animated: true, completion: {
    presentingViewController?.present(targetViewController, animated: false, completion: nil)
})

Though you probably see the transition this time, at the end of the completion of sourceViewController's dismiss(), the presentingViewController will be shown till the targetViewController is presented. I don't know whether you expect this behavior. If no, I couldn't come up with a workaround to prevent this for now.

like image 137
Dorukhan Arslan Avatar answered Oct 17 '22 22:10

Dorukhan Arslan


this worked for me

viewControllers = self.navigationController?.viewControllers
viewControllers.remove(at: viewControllers.count - 1)
self.navigationController?.setViewControllers(viewControllers, animated: true)
self.performSegue(withIdentifier: "destinationVC", sender: self)
like image 6
Hosein Safaei Avatar answered Oct 18 '22 00:10

Hosein Safaei